An external api call returns a pair of values:
('status', 'standby')
I thought it was possible to do an assignment like:
theQuery, theResponse = returnVal
So that the value I want (the second) ends up in theResponse, but this doesn't see to be working.
What I am really trying to test is whether theResponse = 'standby'
if theResponse=='standby' then …
A few solutions:
You can use unpack():
theQuery, theResponse = unpack(returnVal)
Alternatively, you do it "manually"
theQuery = returnVal[1]
theResponse = returnVal[2]
Or change your check to do
if returnVal[2]=='standby' then …
If your returnVal is a table with 2 values, there is no automatic unpacking in Lua, you cannot simply do theQuery, theResponse = returnVal
More explanation:
But quite related to this is that in Lua you can have a function returning multiple values, and its return values can be autumatlically unpacked, e.g.
function myfunc()
return 1,2
end
If you do a, b = myfunc() , a would be assigned 1 and b assigned 2
If you do just a = myfunc() a would be assigned 1 and 2 would be discarded.
Note that this is different from doing:
function myotherfunc()
return {1,2}
end
Here myotherfunc is returning a single value, which is a table containing 2 values.
If you now do a, b = myfunc() , a would be assigned the table {1,2} and b would be nil. There is no unpacking of the returned table.
Related
im trying to compare 2 arrays but i dont know how
for example:
local array1 = { 'friend', 'work', 'privat' }
local array2 = { 'apple', 'juice', 'privat' }
if both arrays have the same value it should do a print.
i know i need to work with something like this
for x in ipairs(array1) do
if x == array2 then
print ("Hi")
end
end
but ofcourse it didnt work.
so how can i check if the array1 value contains a values from array2?
Think of it this way: You have to check each element in the first array to its counterpart in the second. If any element is not equal, you know right away that the arrays aren't equal. If every element checks out as equal, the arrays are equal.
local function arrayEqual(a1, a2)
-- Check length, or else the loop isn't valid.
if #a1 ~= #a2 then
return false
end
-- Check each element.
for i, v in ipairs(a1) do
if v ~= a2[i] then
return false
end
end
-- We've checked everything.
return true
end
how can i check if the array1 value contains a values from array2?
#luther's answer will not always work for your question..
If the arrays are different sizes, it completely fails.
If you have an array where similar element are not in the exact same index, it can return a false negative.
for example a = {'one', 'two'}; b = {'two', 'one'} will return false
Using table.sort to solve this would be a band-aid solution without fixing the real problem.
The function below will work with arrays of different sizes containing elements in any order
function array_compare(a, b)
for ia, va in ipairs(a) do
for ib, vb in ipairs(b) do
if va == vb then
print("matching:",va)
end
end
end
end
In array_compare we go through all the combinations of elements in table a and table b, compare them, and print if they are equal.
ipairs(table) uses index, value (instead of just value)
For example
local array1 = { 'friend', 'work', 'privat' }
local array2 = { 'apple', 'juice', 'privat' }
array_compare(array1, array2)
will print
matching: privat
(I'm writing a second answer to account for another possible interpretation of the question.)
If you want to see if array1 contains any value that's also in array2, you can do the following:
Convert array1 to a set. A set is a new table where the array's values become keys whose values are true.
Iterate through array2 to see if any of its values are a key in the set.
local set = {}
for _, v in ipairs(array1) do
set[v] = true
end
for _, v in ipairs(array2) do
if set[v] then
print'Hi'
-- Use a break statement if you only want to say hi once.
end
end
If the arrays are large, this algorithm should be faster than a nested loop that compares every value in array1 to every value in array2.
I am a hobbyest making mods in TableTop Simulator using LUA and have a question that I can not seam to work out.
I have a number of "objects" which is a table in TTS that contains various data for those objects. For example.. obj.position = {x,y,z}... and can be accessed at the axis level as well.
obj.position = {5,10,15} -- x,y,z
obj.position.x == 5
This is an example. The makers of TTS have made it so you can access all the parts like that. So I can acess the object.. and then its various parts. There is a heap, like name, mesh, difuse and a ton more. roations{x,y,z} etc etc
Anyway. I have a table of objects... and would like to order those objects based on the positional data of the x axis.. so highest to lowest. So if I have a table and obj1 in that table is x=3 and obj2 is x=1 and obj3 = x=2 it would be sorted as obj2,obj3,obj1
Pseudo code:
tableOfObjects = {obj1,obj2,obj3}
--[[
tableOfObjectsp[1] == obj1
tableOfObjectsp[2] == obj2
tableOfObjectsp[3] == obj3
tableOfObjectsp[1].position.x == 3
tableOfObjectsp[2].position.x == 1
tableOfObjectsp[4].position.x == 2
--]]
---After Sort it would look this list
tableOfObjects = {obj1,obj3,obj2}
--[[
tableOfObjectsp[1] == obj1
tableOfObjectsp[2] == obj3
tableOfObjectsp[3] == obj2
tableOfObjectsp[1].position.x == 3
tableOfObjectsp[2].position.x == 2
tableOfObjectsp[3].position.x == 1
--]]
I hope I am making sense. I am self taught in the last few months!
So basically I have a table of objects and want to sort the objects in that table based on a single value attached to each individual object in the table. In this case the obj.position.x
Thanks!
You need table.sort. The first argument is the table to sort, the second is a function to compare items.
Example:
t = {
{str = 42, dex = 10, wis = 100},
{str = 18, dex = 30, wis = 5}
}
table.sort(t, function (k1, k2)
return k1.str < k2.str
end)
This article has more information
table.sort(tableOfObjects, function(a, b) return a.position.x > b.position.x end)
This line will sort your table tableOfObjects in descending order by the x-coordinate.
To reverse order, replace > by <.
From the Lua reference manual:
table.sort (list [, comp])
Sorts list elements in a given order, in-place, from list[1] to
list[#list]. If comp is given, then it must be a function that
receives two list elements and returns true when the first element
must come before the second in the final order (so that, after the
sort, i < j implies not comp(list[j],list[i])). If comp is not given,
then the standard Lua operator < is used instead.
Note that the comp function must define a strict partial order over
the elements in the list; that is, it must be asymmetric and
transitive. Otherwise, no valid sort may be possible.
The sort algorithm is not stable: elements considered equal by the
given order may have their relative positions changed by the sort.
So in other words table.sort will sort a table in ascending order by its values.
If you want to order descending or by something other than the table value (like the x-coordinate of your table value's position in your case) you have to provide a function that tells Lua which element will come first.
you can create a function that handles this exact thing:
local function fix_table(t)
local x_data = {};
local inds = {};
local rt = {};
for i = 1, #t do
x_data[#x_data + 1] = t[i].position.x;
inds[t[i].position.x] = t[i];
end
local min_index = math.min(table.unpack(x_data));
local max_index = math.max(table.unpack(x_data));
for i = min_index, max_index do
if inds[i] ~= nil then
rt[#rt + 1] = inds[i];
end
end
return rt;
end
local mytable = {obj1, obj2, obj3};
mytable = fix_table(mytable);
fix_table first takes in every x value inside of the given table, and also places a new index inside the table inds according to each x value (so that they will be ordered from least to greatest), then it gets the smallest value in the x_data array table, which is used to traverse the inds table in order. fix_table checks to make sure that inds[i] is not equal to nil before it increases the size of the return table rt so that every value in rt is ordered from greatest to least, starting at index 1, and ending at index #rt, finally rt is returned.
I hope this helped.
Let's suppose I want to store a list of element. Including some nil values. The position of the values is significant, and I need to represent the absence of a value in the list at a given position.
Here is a problem:
a = {1,2,3,nil,4}
for k,v in ipairs(a) do
print(k,v)
end
print(a[4])
print(a[5])
The for loop will only print elements 1,2 and 3. It stops at nil. The first print statement prints nil, but I'm not sure if it is actually stored in the table or not. (Who knows?) The second print statement prints 4 - as expected.
So here is the question: how to represent a list of elements in a table, and iterate through them efficiently? Given the conditions above, e.g. the position is significant, and some of the positions are "empty". In other words: have no value, but the absence of that value at that position has a meaning.
This is module "null.lua"
local function null(...)
local t, n = {...}, select('#', ...)
for k = 1, n do
local v = t[k]
if v == null then t[k] = nil
elseif v == nil then t[k] = null
end
end
return (table.unpack or unpack)(t, 1, n)
end
_G.null = null
Use null() as encoder and decoder
require("null")
a = {null(1,2,3,nil,4)}
-- the same could be done element-by-element
-- a = {null(1),null(2),null(3),null(nil),null(4)}
for k,v in ipairs(a) do
v = null(v)
print(k,v)
end
print(null(a[4]))
print(null(a[5]))
Lua tables can be used to create any Abstract Data Structure, in your case you indicated that you want a "list". A Lua table is a data structure that combines numeric index based access with key:value access.
Based on your example, you are using the numeric index feature of tables that let you iterate (with ipairs()) through those values. You will not be able to put nil into the table since the numeric index stops at the first nil entry. The remaining values in the table are stored as key:value pairs.
There are several work-arounds, but it depends on why you want a nil in the list. The simplest approach is to use the string "nil" rather than the native data type nil.
a = {1, 2, 3, "nil", 4}
for k,v in ipairs(a) do
print(k,v)
end
The result of this code is:
1 1
2 2
3 3
4 nil
5 4
Because of the way Lua implements strings, there is not a performance penalty for comparing to the string "nil" versus comparing to the native type nil.
The issue of "holes" (caused by nil) in an array are discussed in Programming in Lua, Chapter 5 Tables. Roberto Ierusalimschy recommendation is to track the size of the array to avoid problems with holes.
The following code shows an Object Oriented approach to tracking the size of the list. There are many possible variations on this theme.
function makeList(...)
local list = table.pack(...)
list.length =
function(self) return self.n
end
list.append =
function(self, value)
self.n = self.n + 1
self[self.n] = value
end
list.print =
function(self)
for i = 1, self.n do print(i, self[i]) end
end
return list
end
a = makeList(1, 2, 3, nil, 4)
a:append(5)
a:print()
print(a:length())
The result is:
1 1
2 2
3 3
4 nil
5 4
6 5
6
Note that the function table.pack creates a field 'n' which contains the correct number of items even when 'nil' is present. See PIL chapter 6.2, Variadic Functions for a complete explanation.
Don't just hack something together, write your own datastructure for this. If you "overload" ipairs (by writing an appropriate iterator) you can use it as a table:
function create(...)
local t = table.pack(...)
local self = {
num = t.n,
elements = { ... }
}
return self
end
function elements(t)
local f = function(s, i)
i = i + 1
if i <= s.num then
return i, s.elements[i]
end
end
return f, t, 0
end
local seq = create(1, 2, nil, 3)
print(seq.num)
for i, e in elements(seq) do
print(i, e)
end
-- results:
-- 4
-- 1 1
-- 2 2
-- 3 nil
-- 4 3
You could know define a metatable for this structure and have it use its own ipairs, so you don't even have to change the name.
Well, you can't store nil in the table without issues.
The most simple solution here would be to introduce your own unique value.
local mynil = {} -- every new table is unique!
a = {1,2,3,mynil,4}
for k,v in ipairs(a) do
if (v == mynil) then
v = nil
end
print(k,v)
end
No more issues with "nil" string that might be stored in the table as well, the minor issue is one more comparison. ipairs or any other iterator will show that the key with mynil value exists. That means you can separate mynil key existence with missing key =nil.
P.S. If you want to shift your list, you may consider table.remove(list, key) function.
The answer to this is rather simple, and these "workaround a" suggested is definitely overkill. Just keep track of the number of items in your table whenever it's changed (note: do not use #, you have too keep track manually to deal with nil values) and use a numeric for loop to iterate over it.
I have a function (the caller) that returns certain values. Before they are returned, they are added to by the result of calling another function (the callee), is there a neater way to add the callee function's resultant values to the caller function's resultant values before the are returned?
def funcA() { // Caller Function
def a,b,c
a = blah
b = blah blah
...
def (d,e) = funcB()
a += d // Is there a neater way to encapsulate
b += e // these additions somehow into the previous line? maybe kind of like
// (a,b) += funcB() ?
return [a,b,c]
}
def funcB() { // Callee Function
def d,e
...
return [d,e]
}
to bad we don't have a zip, then something like [a,b].zip()*.sum() would work.
transpose() only gives you the pairs (not the remainder). so this only works, if your lists are the same length:
assert [43,668]==[[1,2,3],[42,666]].transpose()*.sum()
One could attempt to fill shorter list with zeros in this case, so the sum is not influenced (at that point this depends on the type there).
So this function is a workaround:
def zipadd(a,b) {
def l = [a,b]
// iterate over the size of the longer of the two lists
(0..(l*.size().max()-1)).collect{
// get the pairs, filter null, sum both
l*.getAt(it).findAll{it!=null}.sum()
}
}
assert [43,668,3]==zipadd([1,2,3],[42,666])
assert [43,668,3]==zipadd([42,666],[1,2,3])
assert [24,93,0,1]==zipadd([1,0,0,1], [23,93])
If you use pass l directly (a list of lists) instead of a and b this should also work with more than two elements.
Backpack = {Potion = 'backpack',Stack = 'bag',Loot = 'derp', Gold = 'random'}
Backpack[1] ~= 'backpack' -- nope
As you guys can see, I cannot call Backpack[1] since its not a numeral table, how would I generate a table after the construction of Backpack, consisting only of it's values? for example:
Table_to_be_Constructed = {Value of Potion,Value of Stack,Value of Loot,Value of Gold} -- this is what i need
It seems simple but I couldn't find a way to do it.
I need it this way because i will run a numeric loop on Table_to_be_Constructed[i]
To iterate over all the key-value pairs in a table, use the pairs function:
local Table_to_be_Constructed = {}
for key, value in pairs(Backpack) do
table.insert(Table_to_be_Constructed, value)
end
Note: the iteration order is not defined. So, you might want to sort Table_to_be_Constructed afterwards.
By convention, the variable name _ is used to indicate a variable who's value won't be used. So, since you want only the values in the tables, you might write the loop this way instead:
for _, value in pairs(Backpack) do
For the updated question
Backpack has no order (The order in the constructor statement is not preserved.) If you want to add an order to its values when constructing Table_to_be_Constructed, you can do it directly like this:
local Table_to_be_Constructed = {
Backpack.Potion,
Backpack.Stack,
Backpack.Loot,
Backpack.Gold
}
Or indirectly like this:
local items = { 'Potion', 'Stack', 'Loot', 'Gold' }
local Table_to_be_Constructed = {}
for i=1, #items do
Table_to_be_Constructed[i] = Backpack[items[i]]
end