Find the nearest value - lua

I'm looking for a way to find out which value is closest to x in a table and return that.
Lets assume, for a second, X is x=15, we have the table with 4 values {12, 190, 1, 18}, How do I make it so in this case the first key&value is returned?

x = 15
table = {190, 1, 12, 18}
function NearestValue(table, number)
local smallestSoFar, smallestIndex
for i, y in ipairs(table) do
if not smallestSoFar or (math.abs(number-y) < smallestSoFar) then
smallestSoFar = math.abs(number-y)
smallestIndex = i
end
end
return smallestIndex, table[smallestIndex]
end
index, value = NearestValue(table,x)
print(index)
print(value)

I would do something like this:
initialdiff = 1000000000000
selectedkey = -1
values = {12, 190, 1, 18}
x = 15
for key, val in pairs (values) do
currentdiff = math.fabs(val - x)
if (currentdiff < initialdiff) do
initialdiff = currentdiff
selectedkey = key
end
end
-- selectedkey now holds key for closest match
-- values[selectedkey] gives you the (first) closest value

Related

Get all repeated itens from a table in Lua

I need a little help here
Let's suppose I have a table with numbers.
tbl = {'item1' = 6, 'item2' = 1, 'item3' = 6, 'item4' = 3, 'item5' = 2, 'item5' = 3}
I wanna put all repeated numbers in the same table (with key and value) like this:
repeated = {'item1' = 6, 'item3' = 6, 'item4' = 3, 'item5' = 3}
and creat a new one with the "not repeated" numbers:
notrepeated = {'item2' = 1, 'item5' = 2}
Can someone help? Thank you so much.
-- Count the items for each number
local itemsByNum = {}
for item, num in pairs(tbl) do
itemsByNum[num] = (itemsByNum[num] or 0) + 1
end
-- Now move objects to the respective tables
local rep, noRep = {}, {} -- can't use "repeat" as that's a Lua keyword
for item, num in pairs(tbl) do
if itemsByNum[num] > 1 then -- repeated at least once
rep[item] = num
else -- unique number
norep[item] = num
end
end

Check if table contains number

I need to check if a table contains a specific number that is known.
e.g. My variable is {1, 2, 3, 4, 5} and I want to know how I can check if that variable contains the number 3.
Thanks in advance.
Just loop over the values of your table and compare them against the number:
function contains(table, number)
for key, value in pairs(table) do if value == number then return true end end
return false
end
this will search through the values of both hash & list part. Usage based on your example: var = {1, 2, 3, 4, 5}; assert(contains(var, 3)).
If your list is sorted, you can use a binary search:
function contains(t, num)
local upper = #t
local lower = 1
while upper >= lower do
local mid = math.floor((lower + upper) / 2)
local v = t[mid]
if v < num then
lower = mid + 1
elseif v > num then
upper = mid - 1
else -- v == num
return true
end
end
return false
end

How to update/reload table key values

How can i update a key value using another key value as variable which is inside the same table?
local t = {}
t.playerPosition = {x = 0, y = 0, z = 0}
t.positions = {t.playerPosition.x + 1, t.playerPosition.y + 1, t.playerPosition.z + 1}
Then few lines later i update playerPosition
t.playerPosition = {x = 125, y = 50, z = 7}
And then if i print out...
result
t.positions[1] -- outputs 1
t.positions[2] -- outputs 1
t.positions[3] -- outputs 1
expected result
t.positions[1] -- outputs 126
t.positions[2] -- outputs 51
t.positions[3] -- outputs 8
As you can see key positions isnt updating, what could i do to make it possible?
t.positions = {t.playerPosition.x + 1, t.playerPosition.y + 1, t.playerPosition.z + 1}
In the above line, the expressions are evaluated once, and the resulting values are assigned to fields of the subtable. After this point, changes to the fields of t.playerPosition will not cause a reflected change in t.positions.
Metatables can be used to enable such behaviour, by dynamically calculating results when accessing the fields of t.positions.
local t = {}
t.playerPosition = { x = 0, y = 0, z = 0 }
t.positions = setmetatable({}, {
__newindex = function () return false end,
__index = function (_, index)
local lookup = { 'x', 'y', 'z' }
local value = t.playerPosition[lookup[index]]
if value then
return value + 1
end
end
})
print(t.positions[1], t.positions[2], t.positions[3])
t.playerPosition = {x = 125, y = 50, z = 7}
print(t.positions[1], t.positions[2], t.positions[3])

Calling table.sort returns nil

I am trying to sort a table 'array' that contains tables with two keys called 'pt' and 'angle'. I want to sort the 'array' elements regarding their 'angle' value. To my understanding of table.sort this code snippet should do the trick:
local array = {}
-- Some code that calls
-- table.insert(array, {pt = somePt, angle = someAngle})
-- multiple times
local sorted_table = table.sort(array, function(a,b) return a.angle < b.angle end)
However, sorted_table is always nil. Am I doing something wrong here?
table.sort sorts the array part of a table in place. It does not return a new array. If you need to keep the original, you first need to copy to a temporary array.
So, try something like this:
table.sort(array,function(a,b) return a.angle < b.angle end)
table.sort sorts the table in place; that is, it changes the table that you give it and doesn't return a new one.
If you want a sorted copy, you'd first have to make a copy of the table yourself, then sort it.
This could look like this:
local function sorted_copy(tab, func)
local tab = {table.unpack(tab)}
table.sort(tab, func)
return tab
end
That will create a copy of the table (at least the numeric indices up to some random border) and sort it.
there is no secret, there is an algorithm for this sorting, which has been used many times:
function quicksort(t, sortname, start, endi)
start, endi = start or 1, endi or #t
sortname = sortname or 1
if(endi - start < 1) then return t end
local pivot = start
for i = start + 1, endi do
if t[i][sortname] <= t[pivot][sortname] then
local temp = t[pivot + 1]
t[pivot + 1] = t[pivot]
if(i == pivot + 1) then
t[pivot] = temp
else
t[pivot] = t[i]
t[i] = temp
end
pivot = pivot + 1
end
end
t = quicksort(t, sortname, start, pivot - 1)
return quicksort(t, sortname, pivot + 1, endi)
end
local array = {}
table.insert(array, {pt = 1, angle = 2})
table.insert(array, {pt = 4, angle = 9})
table.insert(array, {pt = 1, angle = 5})
table.insert(array, {pt = 2, angle = 7})
table.insert(array, {pt = 2, angle = 1})
table.insert(array, {pt = 5, angle = 2})
local s_t = quicksort(array, "angle")
for k,v in pairs(s_t) do
print(k, "v=", v.pt, v.angle)
end
Output:
1 v= 2 1
2 v= 5 2
3 v= 1 2
4 v= 1 5
5 v= 2 7
6 v= 4 9

Return strings from table values Lua

I am trying to learn how to print strings from a value in a table. For example.
TestTable = { "Apples" = 0, "Oranges" = 1, "Grapes" = 1, "Bananas" = 0}
for i=1, #TestTable do
if TestTable[i] == 1 then
print(TestTable[i]) --> Oranges Grapes
end
end
Not sure if that made sense, but I want to print all the strings with the 1 value.
Unless the __len metamethod is defined, the # operator can only be used on a sequence, but TestTable is not one.
You can use pairs to iterate the table:
TestTable = { Apples = 0, Oranges = 1, Grapes = 1, Bananas = 0}
for k, v in pairs(TestTable) do
if v == 1 then
print(k)
end
end

Resources