Lua iterate over table sorted by values - sorting

I have a table t with many entries like t["name1"] = 42, t["name2"] = 123, ...
I would like to iterate over the table in descending order of the value numbers. How can this be accomplished? I have found methods to create iterator functions that go ordered over the keys of a table, but no way to go over the entries with ordered values.

function pairs_order_by_values_desc(tab)
local keys = {}
for k in pairs(tab) do
keys[#keys + 1] = k
end
table.sort(keys, function(a, b) return tab[a] > tab[b] end)
local j = 0
return
function()
j = j + 1
local k = keys[j]
if k ~= nil then
return k, tab[k]
end
end
end
local t = {}
t.name1 = 42
t.name2 = 123
t.name3 = 99
for k, v in pairs_order_by_values_desc(t) do
print(k, v)
end

Related

get pairs / triple / quadruple... of elements from vector by function

I have a vector with a couple of elements and I want to write a function that returns me all combinations of x items from this vector.
The following code produces the right output for the case x=2 or x=3 or x=4.
However, I can not implement a solution for every possible x following this idea.
values = {'A','B','C','D','E'};
n = length(values);
data2 = {}; % case x=2
for i = 1:n
for j = i+1:n
data2{end+1} = {values{i}, values{j}};
fprintf('%s %s\n',values{i}, values{j})
end
end
data3 = {}; % case x=3
for i = 1:n
for j = i+1:n
for k = j+1:n
data3{end+1} = {values{i}, values{j}, values{k}};
fprintf('%s %s %s\n',values{i}, values{j}, values{k})
end
end
end
data4 = {}; % case x=4
for i = 1:n
for j = i+1:n
for k = j+1:n
for l = k+1:n
data4{end+1} = {values{i}, values{j}, values{k}, values{l}};
fprintf('%s %s %s %s\n',values{i}, values{j}, values{k}, values{l})
end
end
end
end
How would a function look like which would be able to return my data variable?
data = getCombinations(values, x) %values is vector with elements, x is integer value
EDIT
The following code comes pretty close:
data = perms(values)
data = data(:,1:x)
data = unique(data,'rows')
but it still produces output like A,B and B,A
EDIT2
This fixed it somehow but it is not very nice to look at and it does not work for text entries in cells but only for numbers
data = perms(values)
data = data(:,1:x)
data = sort(data,2)
data = unique(data,'rows')
EDIT3
This did it but it is not very nice to look at... Maybe there is a better solution?
function [data] = getCombinations(values,x)
i = 1:length(values);
d = perms(i);
d = d(:,1:x);
d = sort(d,2);
d = unique(d,'rows');
data = v(d);
end
If you don't want repetitions (and your example suggests you don't) then try nchoosek as nchoosek(1:n, x) to give indices:
values = {'A','B','C','D','E'};
n = length(values);
x = 3;
C = nchoosek(1:n, x);
data = values(C)
In the above, each row is a unique combination of 3 of the 5 elements of values.
Alternatively pass in the values directly:
data = nchoosek(values, x);

Fast way to initialize a tensor in torch7

I need to initialize a 3D tensor with an index-dependent function in torch7, i.e.
func = function(i,j,k) --i, j is the index of an element in the tensor
return i*j*k --do operations within func which're dependent of i, j
end
then I initialize a 3D tensor A like this:
for i=1,A:size(1) do
for j=1,A:size(2) do
for k=1,A:size(3) do
A[{i,j,k}] = func(i,j,k)
end
end
end
But this code runs very slow, and I found it takes up 92% of total running time. Are there any more efficient ways to initialize a 3D tensor in torch7?
See the documentation for the Tensor:apply
These functions apply a function to each element of the tensor on
which the method is called (self). These methods are much faster than
using a for loop in Lua.
The example in the docs initializes a 2D array based on its index i (in memory). Below is an extended example for 3 dimensions and below that one for N-D tensors. Using the apply method is much, much faster on my machine:
require 'torch'
A = torch.Tensor(100, 100, 1000)
B = torch.Tensor(100, 100, 1000)
function func(i,j,k)
return i*j*k
end
t = os.clock()
for i=1,A:size(1) do
for j=1,A:size(2) do
for k=1,A:size(3) do
A[{i, j, k}] = i * j * k
end
end
end
print("Original time:", os.difftime(os.clock(), t))
t = os.clock()
function forindices(A, func)
local i = 1
local j = 1
local k = 0
local d3 = A:size(3)
local d2 = A:size(2)
return function()
k = k + 1
if k > d3 then
k = 1
j = j + 1
if j > d2 then
j = 1
i = i + 1
end
end
return func(i, j, k)
end
end
B:apply(forindices(A, func))
print("Apply method:", os.difftime(os.clock(), t))
EDIT
This will work for any Tensor object:
function tabulate(A, f)
local idx = {}
local ndims = A:dim()
local dim = A:size()
idx[ndims] = 0
for i=1, (ndims - 1) do
idx[i] = 1
end
return A:apply(function()
for i=ndims, 0, -1 do
idx[i] = idx[i] + 1
if idx[i] <= dim[i] then
break
end
idx[i] = 1
end
return f(unpack(idx))
end)
end
-- usage for 3D case.
tabulate(A, function(i, j, k) return i * j * k end)

Lua sorting values of tables within table

I am very new to Lua, so please be gentle.
I want a sorted results based on the "error" key. For this example, the output should be:
c 50 70
d 25 50
b 30 40
a 10 20
Here is my script:
records = {}
records["a"] = {["count"] = 10, ["error"] = 20}
records["b"] = {["count"] = 30, ["error"] = 40}
records["c"] = {["count"] = 50, ["error"] = 70}
records["d"] = {["count"] = 25, ["error"] = 50}
function spairs(t, order)
-- collect the keys
local keys = {}
for k in pairs(t) do keys[#keys+1] = k end
-- if order function given, sort by it by passing the table and keys a, b,
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(t, a, b) end)
else
table.sort(keys)
end
-- return the iterator function
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], t[keys[i]]
end
end
end
for k, v in pairs(records) do
for m, n in pairs(v) do
for x, y in spairs(v, function(t,a,b) return t[b] < t[a] end) do
line = string.format("%s %5s %-10d", k, n, y)
end
end
print(line)
end
I found this about sorting a table and tried to implement it. But it does not work, results are not sorted.
table.sort only works when the table elements are integrally indexed. In your case; when you try to call spairs, you are actually calling table.sort on the count and error indices.
First off; remove the ugly, irrelevant nested for..pairs loops. You only need the spairs for your task.
for x, y in spairs(records, function(t, a, b) return t[b].error < t[a].error end) do
print( x, y.count, y.error)
end
And that is all.

randoming a table Corona SDK / Lua

Could anyone help me with a way to randomly fill a table with N values, where the values are 1,...,M allowing no duplicates ?
Cheers.
local M, N, tNonFinal, tFinal = 500, 20, {}, {}
math.randomseed( os.time() )
for i = 1, N, 1 do
local iRandom = math.random(1, M)
while tNonFinal[iRandom] do
iRandom = math.random(1, M)
end
table.insert( tNonFinal, iRandom, true )
tFinal[i] = iRandom
end
Your required table will be tFinal. You can also add a condition where if M < N then N = M end
This may help you...
local myArray = {}
local valueArray = {1,2,3,4,5,6,7,8,9,10} -- let it be the array with values 1,2...M
local index = 0
local isFetched = {}
for i=1,#valueArray do
isFetched[i] = 0
end
local randomValue = 0
local function addTomyArray()
randomValue = math.random(#valueArray)
if(isFetched[randomValue]==0)then
index = index + 1
isFetched[randomValue] = 1
myArray[index] = valueArray[randomValue]
if(index==#valueArray)then
for i=1,#myArray do
print(myArray[i]) -- result : shuffled array
end
end
else
addTomyArray()
end
end
timer.performWithDelay(0,addTomyArray,#valueArray) -- #valueArray
Keep coding........ 😃

copying unordered keys from one table to ordered values in another

I have a table mapping strings to numbers like this:
t['a']=10
t['b']=2
t['c']=4
t['d']=11
From this I want to create an array-like table whose values are the keys from the first table, ordered by their (descending) values in the first table, like this:
T[1] = 'd' -- 11
T[2] = 'a' -- 10
T[3] = 'c' -- 4
T[4] = 'b' -- 2
How can this be done in Lua?
-- Your table
local t = { }
t["a"] = 10
t["b"] = 2
t["c"] = 4
t["d"] = 11
local T = { } -- Result goes here
-- Store both key and value as pairs
for k, v in pairs(t) do
T[#T + 1] = { k = k, v = v }
end
-- Sort by value
table.sort(T, function(lhs, rhs) return lhs.v > rhs.v end)
-- Leave only keys, drop values
for i = 1, #T do
T[i] = T[i].k
end
-- Print the result
for i = 1, #T do
print("T["..i.."] = " .. ("%q"):format(T[i]))
end
It prints
T[1] = "d"
T[2] = "a"
T[3] = "c"
T[4] = "b"
Alexander Gladysh's answer can be simplified slightly:
-- Your table
local t = { }
t["a"] = 10
t["b"] = 2
t["c"] = 4
t["d"] = 11
local T = { } -- Result goes here
-- Store keys (in arbitrary order) in the output table
for k, _ in pairs(t) do
T[#T + 1] = k
end
-- Sort by value
table.sort(T, function(lhs, rhs) return t[lhs] > t[rhs] end)
-- Print the result
for i = 1, #T do
print("T["..i.."] = " .. ("%q"):format(T[i]))
end
Tables in Lua do not have an order associated with them.
When using a table as an array with sequential integer keys from 1 to N, the table can be iterated in order using a loop or ipairs().
When using keys that are not sequential integers from 1 to N, the order can not be controlled. To get around this limitation a second table can be used as an array to store the order of the keys in the first table.

Resources