I'm pretty new in lua and I have a problem that I've been trying to solve for several hours now.
So simply I have one table with 4 other tables (sry idk how it's named).
local myTable = {
player1 = {id = 1, points = 100},
player2 = {id = 3, points = 200},
player3 = {id = 4, points = 150},
player4 = {id = 7, points = 150}}
Id and points are random numbers.
All I want to do is get only 2 first tables from that table and use their values.
player1 = {id = 1, points = 100}
player2 = {id = 3, points = 200}
I would really appreciate your help, it's very tiring.
All I want to do is get only 2 first tables from that table and use
their values.
To get the inner tables just index myTable with the keys you've stored to inner tables at.
local table1 = myTable.player1
local table2 = myTable.player2
print("Player 1 has " .. table1.points .. " points")
How to get x first objects from table - lua
To answer this you would need to have a table with an order. Lua doesn't know the order of your table unless you have numerical keys.
If your table was like
local players = {
{id = 1, points = 100},
{id = 3, points = 200},
{id = 4, points = 150},
{id = 7, points = 150}}
You would simply pick players[1] and so forth to get the first x elements.
In your case you could do something like
myTable["player"..i] for i from 1 to x assuming that the keys represent the table order.
First you need is sort your table:
local myTable = {
{id = 1, points = 100},
{id = 3, points = 200},
{id = 4, points = 150},
{id = 7, points = 150}
}
You don't need to index those values as 'player1', 'player2', etc. So if you want the index(es) to appear as player1, etc. return the index and concatenated as player, like:
for key, value in pairs(myTable) do
print('player' .. key)
end
The past code will print all table indexes with prefix 'player'.
But to get only the first two values; what we can do? Simple! Make a function:
local myTable = {
{id = 1, points = 100},
{id = 3, points = 200},
{id = 4, points = 150},
{id = 7, points = 150}
}
local function collect(table, howMuch)
local response, index = {}, 1
for key, value in pairs(table) do
response[key] = howMuch and index <= howMuch and value or nil
index = index + 1
end
return response
end
local response = collect(myTable, 2)
print(response[1].id, response[2].id, response[3]) -- 1, 3, nil
What this function do?
Collect values from the first argument named table, and in base the second argument named howMuch (as a max of the response) return those values.
Or for friends: iters table myTable and only returning a table containing 2 fields.
Related
I have already seen many threads with examples of how to do this, the problem is, I still can't do it.
All the examples have tables with extra data. For example somethings like this
lines = {
luaH_set = 10,
luaH_get = 24,
luaH_present = 48,
}
or this,
obj = {
{ N = 'Green1' },
{ N = 'Green' },
{ N = 'Sky blue99' }
}
I can code in a few languages but I'm very new to Lua, and tables are really confusing to me. I can't seem to work out how to adapt the code in the examples to be able to sort a simple table.
This is my table:
local players = {"barry", "susan", "john", "wendy", "kevin"}
I want to sort these names alphabetically. I understand that Lua tables don't preserve order, and that's what's confusing me. All I essentially care about doing is just printing these names in alphabetical order, but I feel I need to learn this properly and know how to index them in the right order to a new table.
The examples I see are like this:
local function cmp(a, b)
a = tostring(a.N)
b = tostring(b.N)
local patt = '^(.-)%s*(%d+)$'
local _,_, col1, num1 = a:find(patt)
local _,_, col2, num2 = b:find(patt)
if (col1 and col2) and col1 == col2 then
return tonumber(num1) < tonumber(num2)
end
return a < b
end
table.sort(obj, cmp)
for i,v in ipairs(obj) do
print(i, v.N)
end
or this:
function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end
for name, line in pairsByKeys(lines) do
print(name, line)
end
and I'm just absolutely thrown by this as to how to do the same thing for a simple 1D table.
Can anyone please help me to understand this? I know if I can understand the most basic example, I'll be able to teach myself these harder examples.
local players = {"barry", "susan", "john", "wendy", "kevin"}
-- sort ascending, which is the default
table.sort(players)
print(table.concat(players, ", "))
-- sort descending
table.sort(players, function(a,b) return a > b end)
print(table.concat(players, ", "))
Here's why:
Your table players is a sequence.
local players = {"barry", "susan", "john", "wendy", "kevin"}
Is equivalent to
local players = {
[1] = "barry",
[2] = "susan",
[3] = "john",
[4] = "wendy",
[5] = "kevin",
}
If you do not provide keys in the table constructor, Lua will use integer keys automatically.
A table like that can be sorted by its values. Lua will simply rearrange the index value pairs in respect to the return value of the compare function. By default this is
function (a,b) return a < b end
If you want any other order you need to provide a function that returs true if element a comes befor b
Read this https://www.lua.org/manual/5.4/manual.html#pdf-table.sort
table.sort
Sorts the list elements in a given order, in-place, from list[1] to
list[#list]
This example is not a "list" or sequence:
lines = {
luaH_set = 10,
luaH_get = 24,
luaH_present = 48,
}
Which is equivalent to
lines = {
["luaH_set"] = 10,
["luaH_get"] = 24,
["luaH_present"] = 48,
}
it only has strings as keys. It has no order. You need a helper sequence to map some order to that table's element.
The second example
obj = {
{ N = 'Green1' },
{ N = 'Green' },
{ N = 'Sky blue99' }
}
which is equivalent to
obj = {
[1] = { N = 'Green1' },
[2] = { N = 'Green' },
[3] = { N = 'Sky blue99' },
}
Is a list. So you could sort it. But sorting it by table values wouldn't make too much sense. So you need to provide a function that gives you a reasonable way to order it.
Read this so you understand what a "sequence" or "list" is in this regard. Those names are used for other things as well. Don't let it confuse you.
https://www.lua.org/manual/5.4/manual.html#3.4.7
It is basically a table that has consecutive integer keys starting at 1.
Understanding this difference is one of the most important concepts while learning Lua. The length operator, ipairs and many functions of the table library only work with sequences.
This is my table:
local players = {"barry", "susan", "john", "wendy", "kevin"}
I want to sort these names alphabetically.
All you need is table.sort(players)
I understand that LUA tables don't preserve order.
Order of fields in a Lua table (a dictionary with arbitrary keys) is not preserved.
But your Lua table is an array, it is self-ordered by its integer keys 1, 2, 3,....
To clear up the confusing in regards to "not preserving order": What's not preserving order are the keys of the values in the table, in particular for string keys, i.e. when you use the table as dictionary and not as array. If you write myTable = {orange="hello", apple="world"} then the fact that you defined key orange to the left of key apple isn't stored. If you enumerate keys/values using for k, v in pairs(myTable) do print(k, v) end then you'd actually get apple world before orange hello because "apple" < "orange".
You don't have this problem with numeric keys though (which is what the keys by default will be if you don't specify them - myTable = {"hello", "world", foo="bar"} is the same as myTable = {[1]="hello", [2]="world", foo="bar"}, i.e. it will assign myTable[1] = "hello", myTable[2] = "world" and myTable.foo = "bar" (same as myTable["foo"]). (Here, even if you would get the numeric keys in a random order - which you don't, it wouldn't matter since you could still loop through them by incrementing.)
You can use table.sort which, if no order function is given, will sort the values using < so in case of numbers the result is ascending numbers and in case of strings it will sort by ASCII code:
local players = {"barry", "susan", "john", "wendy", "kevin"}
table.sort(players)
-- players is now {"barry", "john", "kevin", "susan", "wendy"}
This will however fall apart if you have mixed lowercase and uppercase entries because uppercase will go before lowercase due to having lower ASCII codes, and of course it also won't work properly with non-ASCII characters like umlauts (they will go last) - it's not a lexicographic sort.
You can however supply your own ordering function which receives arguments (a, b) and needs to return true if a should come before b. Here an example that fixes the lower-/uppercase issues for example, by converting to uppercase before comparing:
table.sort(players, function (a, b)
return string.upper(a) < string.upper(b)
end)
So, i have empty table.
local data_tbl = {}
But i need save data when user complete current task.
Like:
-- (1, 2, 21) it's task id.
data_tbl['1'] = true
data_tbl['2'] = true
data_tbl['21'] = true
And in table "data_tbl" it's look like
data_tbl {
1 = true,
2 = true,
21 = true,
}
I wan't saving only completed task. Not all , because it's very heavy ?
But when i wanted remove this key , like 21 , i'ts get nothing effect.
table.remove(data_tbl, 21)
Task with 21 index not removed. Why ?
Maybe have other best way for all this ? (Saving complete tasks)
I don't want use table.Add() because it's added to last position. Like table.Add(data_tbl, {completed_id = 21})
And in table it's look like.
data_tbl {
1 = {completed_id = 21}
}
-- It's get me more table checks... and cycles , i don't want.
table.insert and table.remove are meant for sequences, but you're using the table as a map. If you have a key, say 21 and want to unset it, just do data_tbl[21] = nil
lua tables are hash tables, to insert data to table use mytable[name] = value or mytable.myname = value, to remove from table mytable[name] = nil or mytable.myname = nil.
To simulate arrays lua tables has helper functions in module table and some sort of optimizations, but id's must be numbers and begin with 1.
For mixed tables like mytable[1] = true; mytable[2] = true; mytable[3] = true; mytable[21] = true; mytable.name = 'values', #mytable evaluates to length of 3 as entries [21] and 'name' do not form the sequence.
table.remove and table.insert modifies 'array' shifting corresponding elements:
local mytable = {1, 2, 3, 4}
table.remove(mytable, 2)
print(table.concat(mytable, ',')) -- result is {1, 3, 4 }
table.insert(mytable, 2, 5)
print(table.concat(mytable, ',')) -- result is {1, 5, 3, 4 }
Numeric strings as keys will be not converted internally into numbers (like in javascript) and will not work with array like methods:
local mytable = {}
mytable[21] = 'value21'
mytable['21'] = 'string21'
-- table content: {[21] = 'value21', ['21'] = 'string21'}
Apologizes if the semantics is erroneous in my question, but the code below should explain what my goal is.
I've created a table like so:
local a1 = {}
a1.hammer = {
price = 10,
quantity = 5,
category = "tools",
}
a1.saw = {
price = 15,
quantity = 4,
category = "tools",
}
a1.screwdriver = {
price = 4,
quantity = 12,
category = "tools",
}
Printing the contents of this table gives:
{hammer = {price = 10,
quantity = 5,
category = "tools"},
saw = {price = 15,
quantity = 4,
category = "tools"},
screwdriver = {price = 4,
quantity = 12,
category = "tools"}}
Question 1: How do I access the price of the screwdriver (ie. field of a table of a table)
Question 2:
How do I:
Save table a1 to a file
Open the file and import the table the next time I run the application
Note: local a2 = a1 returns nil for a2 rather than assigning the reference of a1 to a2. There's an issue here...
#Luke Allison
I may have an answer to your first question:
Question 1: How do I access the price of the screwdriver (ie. field of
a table of a table)
you can try this code:
print( a1["screwdriver"]["price"] )
Result = 4.
As for the second question you should have a look at the link in the comments above.
Hope that helps.
I have some space top with fields:
-id,
-status,
-rating
I have two indexes for space top:
--primary
box.space.top:create_index('primary', { type = 'TREE', unique = true, parts = { 1, 'NUM' } })
--status
box.space.top:create_index('status', { type = 'TREE', unique = false, parts = { 2, 'NUM' } })
I can select by id or status
--select by id
space.top.index.primary:select(someId)
--select by status with limit/offset
space.top.index.status:select({someStatus}, {iterator = box.index.EQ, offset = 0, limit = 20})
Sometimes i need select by status with ordering by rating.
What is the best way? Create another index with parts status, rating and make some tricky query if it`s possible? Or continue select by status and make sort by rating in Lua procedure?
Thanks!
UPD:
Thanks, Kostya!
I modified index status like this:
box.space.top:create_index('status_rating', { type = 'TREE', unique = false, parts = { 2, 'NUM', 3 'NUM' } })
And now i can query:
local active_status = 1
local limit = 20
local offset = 0
box.space.top.index.status_rating:select({active_status}, {iterator = box.index.LE, offset=offset, limit=limit})
Great!
Doesn't make sense to create the third index, if you need to order by rating, just include it into the second index as the second part, and use GE/GT iterator, the data will come out ordered. This is an in-memory database, adding more parts to an index doesn't use up more memory, only slows down insertion a bit.
Call with GE/LE iterator and partial index may work not as expected than there is no matching tuples or limit is too high.
Suppose, we have following tuples (status, rating):
{ 1, 1 }
{ 3, 1 }
{ 3, 2 }
Than call
box.space.top.index.status_rating:select({2}, {iterator = box.index.GE, limit=1})
will return tuple {3, 1} as it greater than {2}
And call
box.space.top.index.status_rating:select({1}, {iterator = box.index.GE, limit=2})
will return two tuples {1, 1}, {3, 1}
In both case tuple {3, 1} may be not expected
I have a table in lua with some data.
sometable = {
{name = "bob", something = "foo"},
{name = "greg", something = "bar"}
}
I then want to loop through the table and assign a number to each name as a variable. New to lua and tried it like this.
for i,t in ipairs(sometable) do
t.name = i
end
I was then assuming print("name1", bob) would give me name1 = 1. Right now I'm getting nil. So I'm back to my ugly static list of variables till some kind soul tells me how I'm an idiot.
> sometable = {{name = "bob", something = "foo"},{name = "greg", something = "bar"}}
> for i,t in ipairs(sometable) do t[t.name] = i end
> for i,t in ipairs(sometable) do for j,u in pairs (t) do print (j,u) end end
name bob
something foo
bob 1
greg 2
something bar
name greg
> return sometable[1].bob
1>
The ipairs function will iterate only through numerically indexed tables in ascending order.
What you want to use is the pairs function. It will iterate over every key in the table, no matter what type it is.