Create a numerical table from the values of a non numerical table - lua

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

Related

lua - how to compare different array

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.

How to order a Table to tables based on 1 single data part of it?

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.

How to make a class table member distinct in Lua objects?

Consider the following code:
#!/usr/bin/lua
local field =
{
name = '',
array = {},
new = function(self, o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end,
}
local fld1 = field:new()
local fld2 = field:new()
fld1.name = 'hello'
table.insert(fld1.array, 1)
table.insert(fld1.array, 2)
table.insert(fld1.array, 3)
fld2.name = 'me'
table.insert(fld2.array, 4)
table.insert(fld2.array, 5)
print('fld1: name='..fld1.name..' len='..#fld1.array)
print('fld2: name='..fld2.name..' len='..#fld2.array)
The output when executed is as follows:
fld1: name=hello len=5
fld2: name=me len=5
From the output, it can be seen that name has different values in fld1 and fld2. array, however, has the same value in fld1 and fld2 (fld1.array and fld2.array are the same and therefore have the same length of 5).
How do I fix this code so that fld1.array is independent of fld2.array (so that modifying fld1.array does not change fld2.array)?
First off, fld1 and fld2 have distinct names because you gave them distinct names - their own properties.
When you perform table key assignment the new key and value are stored directly in the table that you specify. The __index metamethod only comes in to play when you perform table key lookup and the key is not found in the table.
A quick example where we can see that table key assignment will shadow keys in the __index lookup chain.
local Foo = { shared = 'shared', private = 'private' }
Foo.__index = Foo
local foo = setmetatable({}, Foo)
foo.private = 'a shadowed value'
print(Foo.shared, foo.shared) -- shared shared
print(Foo.private, foo.private) -- private a shadowed value
Note: there is a __newindex metamethod for catching table key assignment that involves a never-before-seen key.
Consider treating the new method more like a traditional constructor function, wherein you assign 'private' properties to newly created instances.
local Field = {
-- shared properties go here
}
-- shared methods are defined as such
function Field:new (name)
local o = {
-- private properties for the newly created object go here
name = name or '',
array = {}
}
self.__index = self
return setmetatable(o, self)
end
function Field:insert (value)
table.insert(self.array, value)
end
local fld1 = Field:new('hello')
local fld2 = Field:new('me')
fld1:insert(1)
fld1:insert(2)
fld1:insert(3)
fld2:insert(4)
fld2:insert(5)
print('fld1: name='..fld1.name..' len='..#fld1.array) -- fld1: name=hello len=3
print('fld2: name='..fld2.name..' len='..#fld2.array) -- fld2: name=me len=2
Some more notes:
Generally, 'class' names should be in PascalCase, to make them distinct.
Having a :new function in the lookup chain means instances can invoke it, this may or may not be desirable. (Can create slightly ugly inheritance this way.)
There is a difference between how you define methods which use the implicit self. You should give Chapter 16 of Programming in Lua a read. It might be a tad dated if you're using 5.2 or 5.3, but it should still have a lots of useful information.
If you're interested in a tiny library for this, I recently wrote Base. If you look around, you'll find lots of little OOP packages for making these kinds of things a bit easier.
Lua's oop technic not same c++, java
__index metamethod reference target table record.
and so, fld1, fld2 array item is Field's array item.
you must make a new table and use it.
why name's value different. Because, Your assign a name
fld1.name = 'hello'
simply code fix
fld1.array = {}
using new method code fix
local o1 = {name = '', array = {}}
local o2 = {name = '', array = {}}
local fld1 = field:new(o1)
local fld2 = field:new(o2)
make new table(make o) and insert new method.

how to dynamically name element in a lua table

I have the following test code:
local luatable = {}
luatable.item1 = 'abc'
luatable.item2 = 'def'
I'd like to know how to change it so that I can dynamically assign the names becuase I don't know how many "items" I have. I'd like to do something like this:
(pseudo code)
n = #someothertable
local luatable = {}
for i = 1, n do
luatable.item..i = some value...
end
Is there a way to do this?
I'd like to do something like this: luatable.item..i = value
That would be
luatable['item'..i] = value
Because table.name is a special case shorthand for the more general indexing syntax table['name'].
However, you should be aware that Lua table indexes can be of any type, including numbers, so in your situation you most likely just want:
luatable[i] = value
Yes, and the correct code is
for i = 1, n do
luatable["item"..i] = some value...
end
Recall that luatable.item1 is just sugar for luatable["item1"].

How to quickly initialise an associative table in Lua?

In Lua, you can create a table the following way :
local t = { 1, 2, 3, 4, 5 }
However, I want to create an associative table, I have to do it the following way :
local t = {}
t['foo'] = 1
t['bar'] = 2
The following gives an error :
local t = { 'foo' = 1, 'bar' = 2 }
Is there a way to do it similarly to my first code snippet ?
The correct way to write this is either
local t = { foo = 1, bar = 2}
Or, if the keys in your table are not legal identifiers:
local t = { ["one key"] = 1, ["another key"] = 2}
i belive it works a bit better and understandable if you look at it like this
local tablename = {["key"]="value",
["key1"]="value",
...}
finding a result with : tablename.key=value
Tables as dictionaries
Tables can also be used to store information which is not indexed
numerically, or sequentially, as with arrays. These storage types are
sometimes called dictionaries, associative arrays, hashes, or mapping
types. We'll use the term dictionary where an element pair has a key
and a value. The key is used to set and retrieve a value associated
with it. Note that just like arrays we can use the table[key] = value
format to insert elements into the table. A key need not be a number,
it can be a string, or for that matter, nearly any other Lua object
(except for nil or 0/0). Let's construct a table with some key-value
pairs in it:
> t = { apple="green", orange="orange", banana="yellow" }
> for k,v in pairs(t) do print(k,v) end
apple green
orange orange
banana yellow
from : http://lua-users.org/wiki/TablesTutorial
To initialize associative array which has string keys matched by string values, you should use
local petFamilies = {["Bat"]="Cunning",["Bear"]="Tenacity"};
but not
local petFamilies = {["Bat"]=["Cunning"],["Bear"]=["Tenacity"]};

Resources