Ordered lua table looping using C API - c++

Consider the following lua table:
foo = {
bar1 = {a = 1, b = 2, c = "hello"},
bar2 = {a = 5, b = 2, c = "bbq"},
bar3 = {a = 76, b = 13, c = "pwnd"}
}
I am trying to iterate this table using the lua C API to retrieve the key names, bar1, bar2 and bar3. I used the lua_next(L, -2) function to iterate as suggested by many, but the problem is that it returns the elements in random order. The order changes on each run.
I use the following code:
for( lua_pushnil(L); lua_next(L, -2) != 0; lua_pop(L, 1) )
{
printf("%s\n", lua_tostring(L, -2));
}
Most of the time, the output is unordered, such as bar2 bar1 bar3. When lucky, it's ordered. Is there an easy way to loop the table keys in an ordered fashion? What would be the equivalent code as I use, but ordered? Thanks!
Edit:
I know I am using a map rather than an array. But in lua script we have ipairs which would work just fine for this case. I'm looking at the C API equivalent. I've found this stackoverflow answer which gives a different answer, but it doesn't work for me, so I wonder if that answer is good or relevant.

No. The order that Lua traverses tables is undefined.
If you know that the keys are of the form barXXX, then you can create these keys as strings dynamically in the order you wish and then get the corresponding value from the table.

Put the names in a C array, and then order them in C.
As others are saying, the order of keys returned by the hash portion of a table is not guaranteed.
Alternatively, use an array-like structure so you can use the array part:
foo = {
{name = 'bar1', a = 1, b = 2, c = "hello"},
{name = 'bar2', a = 5, b = 2, c = "bbq"},
{name = 'bar3', a = 76, b = 13, c = "pwnd"}
}
So you can use ipairs or the equivalent to for i=1,#foo to iterate over the items in order.

Checking Lua's documentation, the main structure that Lua supports is a Hash Table. Given that it's always going to be a hash-table, you'd probably want to reimplement foo as an array. The bar1, bar2, etc can be part of the entry into the array like so:
foo = {}
foo[0] = {name='bar1', ...}
foo[1] = {name='bar2', ...}
...
or as #lhf suggested, just build the bar names inside a for-loop (if you know it's in sequence) and retrieve the values from foo table.

Related

Crystal: how to increase the number of types an array can hold after instantiation

I'm building a table of data. At first, the rows of this table are most easily filled by key / value so I use a hash
a = Hash(Int32, Symbol).new
a[1] = :one
Once that's done, it's more convenient to work with an array (I need to sort the data for example). Easy enough:
a.to_a # => [{1, :one}]
But now I'm discovering that for my formatter to work properly (multi-page table, using latex) things just make more sense if I can store another data type in that array, for example, a string. But it's too late! The type of the array is fixed; it won't admit a string.
a << "str" # => ERROR!
The solution I've come up with so far doesn't seem very elegant:
a = Hash(Int32, Symbol).new
a[1] = :one
arr = Array(String | Tuple(Int32, Symbol)).new
a.each do |k,v|
arr << {k,v}
end
arr << "str" # no problem now
Is there a more "Crystal" / elegant way?
Just use to_a with as it can be used to cast to a "bigger" type as the docs call it
a = Hash(Int32, Symbol).new
a[1] = :one
arr = a.to_a.map { |x| x.as(String | Tuple(Int32, Symbol)) }
arr << "str" # [{1, :one}, "str"]

I need a code which sums different numbers

I got a very difficult assignment as I am new to python, I hope you will be able to help me.
I wrote this code:
def hours_per_student(student_course,course_hours):
new={}
for key in student_course.keys():
for val in student_course.values():
for m in range(len(val)):
if not new.has_key(key):
new[key]=course_hours[val[m]]
else:
new[key]=new[key]+course_hours[val[m]]
return new
for these dictionaries:
student_course = {'rina' : ['math', 'python'], 'yossi' : ['chemistry', 'biology'], 'riki' : ['python']}
course_hours = {'math' : 4, 'python' : 4, 'chemistry' : 6, 'biology' : 5}
And I need to get this:
hours_per_student(student_course, course_hours)
to return this:
{'rina': 8, 'yossi': 11, 'riki': 4}
But I keep getting identical numbers for each key.
You shouldn't be iterating over .values() if you're already iterating over .keys(), just use the key to get the value. Or where you have for m in len(val), just do for m in val and then reference m instead of val[m](the naming here stinks but I discuss that later). Python is much better at iteration than that. For instance, instead of the line
for val in student_course.values():
you should try something like
for courses in student_course[key]:
for course in courses:
if key not in new:
new[key] = course_hours[course]
else:
new[key] += course_hours[course]
Naming your variables intelligently will make it easier for you to keep track of what's happening. For example, each value in student_course is a list of courses, so you should name it that, not something ambiguous like val. Similarly, each element in courses is the name of a course, so name it as such.
Here you go:
solution = {student: sum([hours.get(course, 0) for course in s_courses]) for student, s_courses in student_course.items()}
Here are the things I found lacking in your code:
When iterating over your students, you could have just created a key for each of them, and then add the hours per course.
Naming variables so you understand what they mean is confused, refrain from using new, key or val.
You don't have to use keys() function, iterating a dictionary using for key in dictionary works the same way.
Here's a fixed code snippet:
def hours_per_student(students, course_hours):
total_hours = {}
for student in students:
courses = students[student]
total_hours[student] = 0
for course in courses:
total_hours[student] += course_hours[course]
return total_hours

How to query list of variables in Matlab struct matching a certain pattern?

Suppose I have the following struct in Matlab (read from a JSON file):
>>fs.
fs.dichte fs.hoehe fs.ts2
fs.temperatur fs.ts3 fs.viskositaet
fs.ts1 fs.ts4
Each one of the fs.ts* components contains another struct. In this particular case, the index of ts goes from 1 to 4, but in another case it could as well be 2 or 7. You get the idea, right? I want the program to be flexible enough to handle any possible input.
So my question comes down to: How to query the maximum index of ts?
In an ideal world, this would work:
who fs.ts*
But unfortunately, it just returns nothing. Any ideas?
(Btw, I'm using Octave and don't have Matlab available for testing; however, there should really be a solution to this which works in both environments.)
You can use fieldnames to get all field names of the struct, then use regexp to extract the ones that start with ts and extract the number. Then you can compare the numbers to find the largest.
fields = fieldnames(fs);
number = str2double(regexp(fields, '(?<=^ts)\d+$', 'once', 'match'));
numbers = number(~isnan(number));
[~, ind] = max(number);
max_field = fields{ind};
max_value = fs.(max_field);
Not an answer to your exact question but sounds like instead of tsN fields, you should have a single ts field with a list.
Tip: every time you see a number in a variable or field name, think whether you shouldn't be using a vector/array/list instead.
This is true for all languages but more so for Octave since everything is arrays. Even if you have three field named ts1, ts2, and ts3 with scalars values, what you really have is three fields whose values are an array of size 1x1.
In Octave you can have two things. Either the value of ts is a cell array, each element of the cell array a scalar struct; or is a struct array. Use a cell array of structs when each struct has different keys, use a struct array when all structs have the same keys.
Struct array
octave> fs.ts = struct ("foo", {1, 2, 3, 4}, "bar", {"a", "b", "c", "d"});
octave> fs.ts # all keys/fields in the ts struct array
ans =
1x4 struct array containing the fields:
foo
bar
octave> fs.ts.foo # all foo values in the ts struct array
ans = 1
ans = 2
ans = 3
ans = 4
octave> numel (fs.ts) # number of structs in the ts struct array
ans = 4
octave> fs.ts(1) # struct 1 in the ts struct array
ans =
scalar structure containing the fields:
foo = 1
bar = a
octave> fs.ts(1).foo # foo value of the struct 1
ans = 1
Cell array of scalar structs
However, I'm not sure if JSON supports anything like struct arrays, you will probably need to have a list of structs. In that case, you will end up with a cell array of struct scalars.
octave> fs.ts = {struct("foo", 1, "bar", "a"), struct("foo", 2, "bar", "b"), struct("foo", 3, "bar", "c"), struct("foo", 4, "bar", "d"),};
octave> fs.ts # note, you actually have multiple structs
ans =
{
[1,1] =
scalar structure containing the fields:
foo = 1
bar = a
[1,2] =
scalar structure containing the fields:
foo = 2
bar = b
[1,3] =
scalar structure containing the fields:
foo = 3
bar = c
[1,4] =
scalar structure containing the fields:
foo = 4
bar = d
}
octave-gui:28> fs.ts{1} # get struct 1
ans =
scalar structure containing the fields:
foo = 1
bar = a
octave-gui:29> fs.ts{1}.foo # value foo from struct 1
ans = 1

List element comparison by iteration over it

1.Three lists a, b and c. If a[index] is in b[index] then get the element in list c corresponding to list b[index]. That is if a[0]=b[1],get c[1]:
a = ['ASAP','WTHK']
b = ['ABCD','ASAP','EFGH','HIJK']
c = ['1','2','3','4','5']
I hope this is what you were looking for. You can add the b and the corresponding c value to the dictionary in a loop if the a array contains the b value. After that you can get the c value by a value as key like in the code below.
a = ['ASAP','WTHK']
# b c
dictionary_trans = {'ASAP' : '1'}
dictionary_trans = {'WTHK' : '1337'}
# etc. put all b values existing in a to the dict
# with thier coresponding c values.
key = a[0]
c_value = dictionary_trans.get(key)
print c_value
My python skills are very limited, but I think I would try to solve the problem this way.
This solution could crash if you use an a value which is not contained in the dictionary, so you need to implement some logic to handle missing relations between a and c, like insert dummy entries to the dictionary or so.

Looping through tables in a table in Lua

I've hit a complete dead end with this. This is probably going to be something incredibly basic and it will most likely result in me smashing my head into a wall for having a major brain fart. My question is basically, how do you loop though tables in lua if the entries are tables themselves?
C++:
lua_newtable(luaState);
for(auto rec : recpay) {
lua_newtable(luaState);
lua_pushnumber(luaState, rec.amount);
lua_setfield(luaState, -2, "Amount");
lua_pushnumber(luaState, rec.units);
lua_setfield(luaState, -2, "Units");
lua_setfield(luaState, -2, rec.type);
}
lua_setglobal(luaState, "RecuringPayments");
Lua:
for _,RecWT in ipairs(RecuringPayments) do
-- RecWT.Amount = nil?
end
In your C++ code it looks like you're setting the subtable by string as a key rather than by index. To traverse that entry you have to use pairs instead:
for recType, RecWT in pairs(RecuringPayments) do
assert(RecWT.Amount ~= nil)
end
Note that ipairs only traverses the index part of the table, the associative part is ignored.
Alternatively, if you want to use index access then you have to set the key-value with lua_settable instead:
lua_newtable(luaState);
int i = 0;
for(auto rec : recpay)
{
lua_newtable(luaState);
lua_pushnumber(luaState, rec.amount);
lua_setfield(luaState, -2, "Amount");
lua_pushnumber(luaState, rec.units);
lua_setfield(luaState, -2, "Units");
lua_pushnumber(luaState, ++i);
lua_insert(luaState, -2);
lua_settable(luaState, -3);
}
lua_setglobal(luaState, "RecuringPayments");
You can use a recursive function that traverses tables:
function traversetable(tab, array)
local iteratefunc = array and ipairs or pairs
for k, v in iteratefunc(tab) do
if type(v) == "table" then
traversetable(v, array) --Assumes that type is the same as the parent's table
else
--Do other stuff
end
end
end
This is just a basic example, but gives you a rough idea. array is a boolean value indicating, whether it's a one-based array or not.