lua table.sort not behaving as expected - sorting

I have a program that evaluates sets of images and assigns them a given value, now I would like to sort the output of this program, to do this I have the following code:
function SelectTop(params,images,count)
local values={}
for k,v in pairs(images) do
local noError,res=pcall(evaluate,params,v)
if noError then
values[v]=res
else
values[v] = 9999999999999999999999999999999999999999999999999999999999
end
end
function compare(a,b)
return a[2] < b[2]
end
table.sort(values,compare)
print(values)
end
where we can reasonably assume the output of evaluate to be akin to math.random(7000) (the actual code is far more complex and involves neural networks).
Now I would expect the output to be sorted but instead I get something like this:
{
table: 0x40299d30 : 4512.3590053809
table: 0x40299580 : 4029.3450116073
table: 0x40298dd0 : 6003.9508240314
table: 0x40297de0 : 6959.9145312802
table: 0x40297630 : 4265.2784117677
table: 0x40296e40 : 3850.0829011681
table: 0x40296690 : 4007.2308907069
table: 0x40296ec0 : 3840.5216952082
table: 0x4029a770 : 5059.1475464564
table: 0x40299fc0 : 6058.9603651599
table: 0x40299810 : 1e+58
table: 0x40299060 : 1e+58
table: 0x402988b0 : 5887.729117754
table: 0x402978c0 : 3675.7295252455
table: 0x40296920 : 1e+58
table: 0x4029aa00 : 5624.6042279879
table: 0x40295bf8 : 1391.8185365923
table: 0x40296458 : 4276.09869066
table: 0x40299aa0 : 1e+58
table: 0x402992f0 : 6334.3641972965
table: 0x40298300 : 2660.5004512843
table: 0x40298b40 : 6200.373787482
table: 0x40296148 : 6178.926312832
table: 0x40298380 : 1559.5307868896
table: 0x40295968 : 1e+58
table: 0x40296bb0 : 6708.7545218628
table: 0x4029b550 : 1484.2931717456
table: 0x40298400 : 1638.1286256175
table: 0x40298070 : 3762.7368939272
table: 0x402963d8 : 1500.002116023
table: 0x4029ac90 : 2486.2695974502
table: 0x40295e88 : 1e+58
table: 0x40297b50 : 4806.6468870717
table: 0x4029a4e0 : 4328.0636461426
table: 0x402973a0 : 4757.4343171052
table: 0x4029a250 : 3998.8649821268
}
So why does table.sort not work here? I would assume that some sort of sorting would happen here?
Anybody know what I'm doing wrong?
So if we want a full example we can do something like this:
function evaluate (a,b)
return math.random(7000)
end
SelectTop(nil,{ {a, b, c}, {d, e, f}, {g, e, f}, {f, e, f} },0)
output:
{ table: 0x41c2af18 : 5560
table: 0x41c2afa8 : 4131
table: 0x41c2af60 : 4892
table: 0x41c2aff0 : 5273
}

table.sort works on arrays, not on dictionaries.
You'll need to replace values[v]=res with something like values[#values+1]= {v, res} and adjust compare accordingly.
Right now table.sort will see empty array - there's no items idx 1/2/3/..., because you're indexing results with image itself.

Related

Search and extract element located in various path of json structure

I have a json in a PostgreSQL database and I need to extract an array not always located in same place.
Problem
Need to extract array choicies of a particular element name
Element name is known, but not where he's sitting in structure
Rules
All elements name are unique
choicies attribute could not be present
JSON structure
pages : [
{
name : 'page1',
elements : [
{ name : 'element1', choicies : [...]},
{ name : 'element2', choicies : [...]}
]
}, {
name : 'page2',
elements : [
{
name : 'element3',
templateElements : [
{
name : 'element4'
choicies : [...]
}, {
name : 'element5'
choicies : [...]
}
]
}, {
name : 'element6'
choicies : [...]
}
]
},{
name : 'element7',
templateElements : [
{
name : 'element8'
choicies : [...]
}
]
}
]
My try to extract elements by flatten the structure
SELECT pages::jsonb->>'name',
pageElements::jsonb ->> 'name',
pageElements::jsonb -> 'choicies',
pages.*
FROM myTable as myt,
jsonb_array_elements(myt.json -> 'pages') as pages,
jsonb_array_elements(pages -> 'elements') as pageElements
Alas column choicies is always null in my results. And that will not work when element is located somewhere else, like
page.elements.templateElements
page.templateElements
... and so on
I don't know if there is a way to search for a key (name) wherever it's sitting in json structure and extract an other key (choicies).
I wish to call a select with element name in parameter return choicies of this element.
By instance, if I call select with element name (element1 or element4 or element8), choicies array (as rows or json or text, no preference here) of this element should be return.
Wow! Solution founded goes belong expectation! JSONPath was the way to go
Amazing what we can do with this.
SQL
-- Use jsonpath to search, filter and return what's needed
SELECT jsonb_path_query(
myt.jsonb,
'$.** ? (#.name == "element_name_to_look_at")'
)->'choices' as jsonbChoices
FROM myTable as myt
Explanation of jsonpath in SQL
jsonb_path_query(jsonb_data, '$.** ? (#.name == "element_name_to_look_at")')->'choices'
jsonb_path_query : posgresql jsonpath function
jsonb_data : database column with jsonb data or jsonb expression
$.** : search everywhere from root element
? : where clause / filter
# : object return by search
#.name == "element_name_to_look_at" : every object name equals element_name_to_look_at
->'choices' : for each object returned by jsonpath, get choices attribute
Final version
After get choices jsonb array, we return a dataset with every choice.
choices arrays look like this :
[{value:'code1',text:'Code Label 1'}, {value:'code2',text:'Code Label 2'},...]
SELECT choices.*
FROM (
-- Use jsonpath to search, filter and return what's needed
SELECT jsonb_path_query(myt.jsonb, '$.** ? (#.name == "element_name_to_look_at")')->'choices' as jsonbChoices
FROM myTable as myt
) choice,
-- Explode json return array into columns
jsonb_to_recordset(choice.jsonbChoices) as choices(value text, text text);

Rethinkdb execute multiple avg in one query

I have a review table with multiple number columns. I would like to count he avg of all columns in one query.
So if the table looks like:
{
foo : 2,
bar : 5,
foobar : 10
},
{
foo : 4,
bar : 3,
foobar : 12
}
then i would like to get the avg for each column in one query. I know I can do:
r.table('stats' ).avg( 'foo' )
on each column but I would like to do this in just one query and map into into just one object.
Any ideas on how to do this?
You can use map with reduce (if every record in table has all 3 fields):
r.table("stats").map(function(row){
return {foo : row("foo"), bar : row("bar") , foobar : row("foobar"), count : 1};
}).reduce(function(left, right){
return {foo : left("foo").add(right("foo")), bar : left("bar").add(right("bar")), foobar : left("foobar").add(right("foobar")), count : left("count").add(right("count"))};
}).do(function (res) {
return {
foo: res('foo').div(res("count")),
bar: res('bar').div(res("count")),
foobar: res('foobar').div(res("count"))
};
})
If record can have not all fields, you can separate count in map operation for each field, and then in do use it depending on field.

SML : Changing value of INT in a structure

I've got a small problem.
I made calculations and all my ids are not following each other anymore (because of some delete during the calculus). Unfortunately, to make my result valid, I need this order... :/
So in order to simply the task, I made an external function, that will "rename" all the IDs but I do not know how to perform this.
Here is the function that I've got :
fun setId (W {id, ...}) =
let
in
print( "[" ^ Int.toString (id) ^ "]");
print( "[" ^ Int.toString (!nextId) ^ "]\n");
Ref.incr nextId
end
(for the one who are wandering appis just a homemade function to perform the same calcul on each element of a list, but it's not important.)
When I'm execute this code, I obtain in output :
[0][0]
[1][1]
[2][2]
[3][3]
[4][4]
[5][5]
[6][6]
[7][7]
[8][8]
[9][9]
[10][10]
[11][11]
[12][12]
[13][13]
[14][14]
[15][15]
[16][16]
[17][17]
[18][18]
[19][19]
[20][20]
[21][21]
[22][22]
[39][23]
[40][24]
[41][25]
[42][26]
[43][27]
[44][28]
[45][29]
[46][30]
[47][31]
[48][32]
[49][33]
[50][34]
[51][35]
[52][36]
[53][37]
as you can see there is a big problem [23] [39] the list does not have following numbers. :/
Basically, I would like the function setIdto be able to modify the ID of the Node. But I don't know how :/
Here is the datatype Node for understanding purposes :
datatype node =
W of {
id : int
, predId : int option
, creationDepcy : Dependency.depcy
, nominalDepcies : Dependency.depcy list ref
, pattern : Termstore.store
, propositions : Propstore.pstore
, nominals : Propstore.pstore
, diamonds : Termstore.store
, boxes : Termstore.store
, disjunctions : Termstore.store
, nglstore : Termstore.store
, lazyProps : Lazystore.store
, lazyNoms : Lazynomstore.store
, lazyBoxes : Lazyboxstore.store
, blockedDiamonds : (Term.index * int) list ref
, branchPoints : int list ref
}
Thanks in advance for your help !
Best Regards.
Since id is typed int it cannot be modified. If you change it to int ref then you can modify it, but you will also have to change the accessors to dereference the ref.
An alternative solution is to create an array that maps from old IDs to new IDs and use this array for presentation, but that seems even more complicated.
Since ints are immutable -- you could take your list of nodes and replace it with a new list of nodes:
fun newID (W(x), i) =
W({
id = i
, predId = #predId x
, creationDepcy = #creationDepcy x
, nominalDepcies = #nominalDepcies x
, pattern = #pattern x
, propositions = #propositions x
, nominals = #nominals x
, diamonds = #diamonds x
, boxes = #boxes x
, disjunctions = #disjunctions x
, nglstore = #nglstore x
, lazyProps = #lazyProps x
, lazyNoms = #lazyNoms x
, lazyBoxes = #lazyBoxes x
, blockedDiamonds = #blockedDiamonds x
, branchPoints = #branchPoints x
});
fun imap _ [] _ = []
| imap f (x::xs) i = f(x,i):: (imap f xs (i+1));
(imap stands for "increment map")
Then if xs is a list of nodes the function call
imap newID xs 0
will yield a new list of nodes with the id fields consecutive ints starting with 0
Disclaimer: I didn't try this on your setup of course, by I created a datatype of records which had an id field and successfully used this approach. Obviously this isn't something you would want to do a lot of because of all the copying, but if it is at one specific point in your code it should be okay.
Mostly equivalent to John's solution, here is how one would update a list of nodes without using references, using a fold instead. The function setId is the same.
fun setIds firstId ws =
#1 (foldr (fn (w,(ws',nextId)) => (setId w nextId::ws', nextId+1)) ([],firstId) ws)
Running setIds 1 [w1, w2, w3, ...] would yield [w1', w2', w3', ...].

String' is not convertible to 'StringLiteralConvertible' in Xcode 7 Beta 5

I'm trying to initialize a dictionary constant with
["updateType" : "moveRow", "data" : rows].
rows is an array. I have is as:
let update = ["updateType" : "moveRow", "data" : rows]
I have also tried:
let update: Dictionary< String, AnyObject> = ["updateType" : MoveRow", "data" : rows]
and
let update: [String : AnyObject] = ["updateType" : "moveRow", "data" : rows]
in each case, I get and error on the key "data" that says:
String' is not convertible to 'StringLiteralConvertible'.
Can anybody explain what's going on?
The problem seems to be in your creation of rows as optional:
var rows: Array<Dictionary<String, AnyObject>>?
If you can get rid of the optional, it should start working. E.g.
let d = ["updateType" : "moveRow", "data" : rows!]
...or by creating the rows like this:
var rows = Array<Dictionary<String, AnyObject>>()

Lua : add a table in a table

I recently started learning Lua and I have a question about tables :
local mytable = {10,11,12}
I would add another table in mytable[3] , if I do this :
table.insert(mytable[3], {[15] = {}})
Will it works ?
And if it works, what will be the "final" result ?
mytable[3][15] = {}
or
mytable[3][1][15] = {}
?
It's probably a basic question but it will help me :p
The first argument of table.insert should be the table being inserted, so the correct syntax is:
table.insert(mytable, {[15] = {}})
After this, the value of mytable[4] (note that Lua table index starts from 1) is the table {[15] = {}}, and the value of mytable[4][15] is therefore an empty table.
To make mytable[3] a table {[15] = {}}, use assignment instead:
mytable[3] = {[15] = {}}

Resources