I am new to lua and want to learn about nested table
This is what I have been trying:
t = {};
t[1] = 22, {1, 22, 3};
t[2] = 44, {4, 5, 6};
t[3] = 66, {4, 5, 6};
for k, v in ipairs(t) do
print(k,v)
end
This does not work for me.
This is the result I want:
Example:
1 2 5
2 5 66
3 6 33
4 2 1
5 4 12
6 4 3
7 2 44
8 3 1
9 2 44
10 3 99
How do I read a nested table like this and
how do I table.insert in the right column?
I believe the misunderstanding lies in this code:
t[1] = 22, {1, 22, 3}
The 2nd value, the one after the comma, {1, 22, 3} is being assigned to nothing, it is dropped in the ether.
Perhaps what you meant was a table of tables:
t[1] = {22, {1, 22, 3}}
This would create an entry at [1] in t that is itself..a table
t[1][1] == 22
t[1][2] == {1, 22, 3}
Then to iterate this setup you could use:
local t = {}
t[1] = {22, {1, 22, 3}}
t[2] = {44, {4, 5, 6}}
t[3] = {66, {4, 5, 6}}
for _,entry in ipairs(t) do
local key = entry[1]
io.write(key .. ' ')
for _,value in ipairs(entry[2]) do
io.write(value .. ' ')
end
io.write('\n')
end
But to be honest, I'm not sure what you're asking as your "expected output" is significantly different than your sample data set.
Replying to Qualmos' comment in payo's answer:
local t = {}
t[1] = {22,3}
t[2] = {44,6}
t[3] = {66,63}
for _,v in pairs(table) do
print(_,v[1],v[2])
end
Would print something like this:
1,22,3
2,44,6
3,66,63
Btw, you can make the table look like this:
local t = {
{22,3};
{44,6};
{66,63};
}
Related
I have database records arranged in an ltree structure (Postgres ltree extension).
I want to filter these items down to the outer most ancestors of the current selection.
Test cases:
[11, 111, 1111, 2, 22, 222, 2221, 2222] => [11, 2];
[1, 11, 111, 1111, 1112, 2, 22, 222, 2221, 2222, 3, 4, 5] => [1, 2, 3, 4, 5];
[1111, 1112, 2221, 2222] => [1111, 1112, 2221, 2222];
1
|_1.1
| |_1.1.1
| |_1.1.1.1
| |_1.1.1.2
2
|_2.2
| |_2.2.2
| |_2.2.2.1
| |_2.2.2.2
3
|
4
|
5
I have implemented this in Ruby like so.
def fetch_outer_most_items(identifiers)
ordered_items = Item.where(id: identifiers).order("path DESC")
items_array = ordered_items.to_a
outer_most_item_ids = []
while(items_array.size > 0) do
item = items_array.pop
outer_most_item_ids.push(item.id)
duplicate_ids = ordered_items.where("items.path <# '#{item.path}'").pluck(:id)
if duplicate_ids.any?
items_array = items_array.select { |i| !duplicate_ids.include?(i.id) }
end
end
return ordered_items.where(id: outer_most_item_ids)
end
I have eliminated descendants as duplicates via recursion. I'm pretty sure there is an SQL way of doing this which will be the preferred solution as this one triggers n+1 queries. Ideally I would add this function as a named scope for the Item model.
Any pointers please?
I have this array and need to replace its elements by the multiplication of its previous and next.
I do the following:
array.each_with_index{|element, index|
next_element = array[index+1]
previous_element = array[index-1]
}
array.map! {|a|
if a == array.first
a = a * next_element
elsif a == array.last
a = a * previous_element
else
a = next_element * previous_element
end
}
I expect the following result:
array = [4, 1, 6, 7, 9, 3, 0] #given array
array = [4, 24, 7, 54, 21, 0, 0] #array replaced
I get the following error:
undefined local variable or method `next_element' for Arrays:Class
Is there a easy way of getting the previous and next element of a given array element?
Am I using the array.map! method right?
This would work:
array = [4, 1, 6, 7, 9, 3, 0]
[nil, *array, nil].each_cons(3).map { |l, m, r| (l || m) * (r || m) }
#=> [4, 24, 7, 54, 21, 0, 0]
The array is surrounded by nil values, so each element has neighbors. each_cons(3) then yiels each element along with its neighbors to map which multiplies the left (l) with the right (r) neighbor, falling back to the middle element (m) if one of the neighbors happens to be nil.
You can do as following,
[array[0..1].inject(:*)] + array[0..-2].map.with_index { |x,i| x * (array[i+2] || array[i+1]) }
# => [4, 24, 7, 54, 21, 0, 0]
You defined next_element and previous_element inside the loop, so they become undefined at the end. This is a simple work around of your code, I'll assume that
you want to keep first and last element unchanged. You dont need to use map
array.each_with_index do |element, index|
if element != array.first && element != array.last
array[index] = array[index+1] * array[index-1]
end
end
array => [4, 24, 168, 1512, 4536, 0, 0]
This is not what you expected, why? Because your element, array[index] will change after each iteration you can print array after each iteration to see the result
I would suggest you to use another array to save the value of array, like this
b =[]
array.each_with_index do |element, index|
b[index] = array[index]
if element != array.first && element != array.last
b[index] = array[index+1] * array[index-1]
end
end
Seems like each_cons would be a good fit here:
[array.first] + array.each_cons(3).map { |p, _, n| p * n } + [array.last]
#=> [4, 24, 7, 54, 21, 0, 0]
This needs some more work (e.g. if the array is empty this will return [nil, nil]) but I'm sure you can figure out these edge cases.
Case1: iterating through a pre-sized table
local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
for i = 1, 10 do
t[i] = i * 2
end
Case2: iterating through an empty table
local t = {}
for i = 1, 10 do
t[i] = i * 2
end
Would there be any performance difference between performing the two loops?
Does Lua internally resize the table before assigning a value?
This question already has answers here:
Inserting an array into every nth element of another
(3 answers)
Closed 6 years ago.
I have the following string and array:
a = '1, 2, 3, 4, 5, 6, 7, 8'
b = ['9', '10', '11', '12']
I need to insert an element of b after every nth comma (2 for this example) into a, resulting in:
a = '1, 2, 9, 3, 4, 10, 5, 6, 11, 7, 8, 12'
I've been playing around with various forms of scan but can't seem to produce the desired result.
Is there an easy way for me to do this?
Use a.split(', '), any solution from your previous question, and join(', ').
With credits to #Stefan :
a = '1, 2, 3, 4, 5, 6, 7, 8'
b = ['9', '10', '11', '12']
enum = Enumerator.new do |y|
e1 = a.split(',').each
e2 = b.each
loop do
y << e1.next.strip << e1.next.strip << e2.next
end
end
puts enum.to_a.join(', ')
#=> 1, 2, 9, 3, 4, 10, 5, 6, 11, 7, 8, 12
You could also use this if you are sure that every number is separated by a comma and a space :
enum = Enumerator.new do |y|
e1 = a.split(', ').each
e2 = b.each
loop do
y << e1.next << e1.next << e2.next
end
end
I am trying to sort a Ruby array with the following function
#prices = #item.prices.sort { |x,y| x.total <=> y.total }
Which orders from the lowest to the highest cost. However some products have a total of 0.00 and I want them to appear last rather than at the top.
I have tried a few things but would like some way to modify this block to sort zero at the bottom but keep the rest in ascending order.
Thanks.
Try this out, I think it is doing what you request:
#prices = #item.prices.sort {|a,b| a.total==0 ? 1 : b.total==0 ? -1 : a.total<=>b.total}
Just for the record:
>> a = [0, 1, 3, 0, 2, 5, 0, 9]
=> [0, 1, 3, 0, 2, 5, 0, 9]
>> a.sort_by { |x| x.zero? ? Float::MAX : x }
=> [1, 2, 3, 5, 9, 0, 0, 0]
On most platforms 1.0/0 will evaluate to Infinity, so you can also use this instead of Float::MAX:
>> b = [1,4,2,0,5,0]
=> [1, 4, 2, 0, 5, 0]
>> Inf = 1.0/0
=> Infinity
>> b.sort_by { |x| x.zero? ? Inf : x }
=> [1, 2, 4, 5, 0, 0]
prices = [0, 1, 2, 0,4, 3]
prices = prices.sort_by do |price|
[
if price == 0
1
else
0
end,
price
]
end
p prices
# => [1, 2, 3, 4, 0, 0]
The trick here is that arrays are compared by comparing their first elements, but if those elements are equal, then by comparing their next elements, and so on. So having the sort_by block yield an array lets you determine primary sort order, secondary sort order, and so on in a clean manner.
So devise a comparator to do that ...
if x.total == 0
# always consider 0 "largest" and no 0 can be larger than another
# (make sure 0.0 is 0 and not a number really close to 0)
# perhaps x or y should be first for other reasons as well?
1
else
# otherwise lower to higher as normal
x.total <=> y.total
end
Or without comments:
foo.sort {|x, y| if x.total == 0 then 1 else x.total <=> y.total end}
Happy coding.
This would feel less hacky and less write-only to me:
prices = prices.sort_by do |price|
zero_status = price.zero? ? 1 : 0
[zero_status, price]
end
because it's an idiomatic way of sorting something by two criteria, which is what you're doing here.