Rails Haml - join hash values by index - ruby-on-rails

- #nutritions = Hash.new
- #ingredients.each_with_index do |ingredient,i|
- ingredient.nutritions.each_with_index do |nutrition, j|
- #nutritions[[i,j]] = nutrition.amount
- #nutritions.each do |nutrition|
= nutrition
gives me two "blocks" with amounts (example has 2 ingredients, with 4 nutritions):
[[ingredient, nutrition], amount]
[[0, 0], 900.0]
[[0, 1], 3769.0]
[[0, 2], 0.0]
[[0, 3], 100.0]
[[1, 0], 258.0]
[[1, 1], 1080.0]
[[1, 2], 64.0]
[[1, 3], 0.0]
I'm searching for a way to add up each hash value (amount),
and store it in another key behind, like
[[2, 0], 1158.0]
[[2, 1], 4849.0]
[[2, 2], 64.0]
[[2, 3], 100.0]
So. If there're 5 ingredients, store the sum of them in the 6th "block"
Solution:
(Thx to Smathy!)
[[0, 0], 900.0]
[[3, 0], 1507.0]
[[0, 1], 3769.0]
[[3, 1], 6310.0]
[[0, 2], 0.0]
[[3, 2], 136.0]
[[0, 3], 100.0]
[[3, 3], 101.0]
[[1, 0], 258.0]
[[1, 1], 1080.0]
[[1, 2], 64.0]
[[1, 3], 0.0]
[[2, 0], 349.0]
[[2, 1], 1461.0]
[[2, 2], 72.0]
[[2, 3], 1.0]

To give you literally what you're asking for:
- #nutritions = Hash.new
- end_of_list = #ingredients.length
- #ingredients.each_with_index do |ingredient,i|
- ingredient.nutritions.each_with_index do |nutrition, j|
- #nutritions[[i,j]] = nutrition.amount
- #nutritions[[end_of_list,j]] ||= 0
- #nutritions[[end_of_list,j]] += nutrition.amount
There's probably a much nicer way to accomplish your real goal, but without knowing what you're actually trying to accomplish it's impossible to guess the best way.

Related

remove duplication from multi- dimensional array in swift 3 [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have such kind array and I want to remove duplicate values in swift 3.0
[[2, 2, 2], [2, 2, 2], [2, 2, 1], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2,
2, 1], [2, 2, 2], [2, 2, 2], [2, 1, 1], [2, 1, 2], [2, 1, 2], [2, 2,
2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 1], [2, 2, 2], [2, 2, 2],
[2, 1, 1], [2, 1, 2], [2, 1, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [1,
1, 1], [1, 1, 2], [1, 1, 2], [1, 2, 2], [1, 2, 2], [1, 2, 2], [2, 2,
2], [2, 2, 2], [2, 2, 2], [2, 2, 2]]
so what code i have to write for this.
Use this code below to filter duplicate arrays and will get in ordered array
let filteredArr = Array(NSOrderedSet(array: arr))

Sort items in cycle

I'm having trouble explaining what I am looking for so I will provide an example, let's say I have this array:
[
[1, 2],
[1, 3],
[1, 4],
[2, 3],
[2, 4],
[3, 4]
]
rather than sorting it by the first column, I would like it to cycle through the first column, so instead of 1, 1, 1, 2, 2, 3 it would do: 1, 2, 3, 1, 2, 1
resulting in:
[
[1, 2],
[2, 3],
[3, 4],
[1, 3],
[2, 4],
[1, 4]
]
Even better would be if it could cycle through both columns to prevent two numbers in a row as much as possible, the ideal solution would sort the original array as:
[
[1, 2],
[3, 4],
[1, 3],
[2, 4],
[1, 4],
[2, 3]
]
Leading to the maximum spacing between repeating numbers for each inner array (both columns being taken into account).
I hope I have provided sufficient information, and I will greatly appreciate any advise, I am fairly clueless so far, searching has yeilded me nothing.
I will only address the first part of your question as I don't understand what you mean by "Even better would be if it could cycle through both columns to prevent two numbers in a row as much as possible...". The clause "as much as possible" is especially troublesome, as it refers to an unspecified criterion.
Let arr be your array. The elements are sorted in your example, but if they were not, the first step would be:
arr.sort!
See Array#sort! and Array#<=> for an explanation of how Ruby sorts arrays whose elements are arrays.
There are many ways to obtain the desired ordering. Here is one that uses Enumerable#chunk:
arr.chunk(&:first).flat_map {|_,a| a.map.with_index {|i,b| [b,i]}}.sort.map(&:last)
#=> [[1, 2], [2, 3], [3, 4], [1, 3], [2, 4], [1, 4]]
The steps are as follows:
e = arr.chunk(&:first)
#=> #<Enumerator: #<Enumerator::Generator:0x007fa01a8141d0>:each>
We can see the elements of this enumerator, which are passed to the block by Enumerator#each (which calls Array#each), by converting it to an array:
e.to_a
#=> [[1, [[1, 2], [1, 3], [1, 4]]], [2, [[2, 3], [2, 4]]], [3, [[3, 4]]]]
Continuing:
f = e.flat_map { |_,a| a.map.with_index { |i,b| [b,i] } }
#=> [[0, [1, 2]], [1, [1, 3]], [2, [1, 4]], [0, [2, 3]], [1, [2, 4]], [0, [3, 4]]]
g = f.sort
#=> [[0, 1, 2], [0, 2, 3], [0, 3, 4], [1, 1, 3], [1, 2, 4], [2, 1, 4]]
g.map(&:last)
#=> [[1, 2], [2, 3], [3, 4], [1, 3], [2, 4], [1, 4]]
Let's look more closely at the calculation of f:
h = e.flat_map
#=> #<Enumerator: #<Enumerator: #<Enumerator::Generator:0x007fa01a8141d0>:each>:flat_map>
h.to_a
#=> [[1, [[1, 2], [1, 3], [1, 4]]], [2, [[2, 3], [2, 4]]], [3, [[3, 4]]]]
You can think of h as a "compound" enumerator.
The first value of h, [1, [[1, 2], [1, 3], [1, 4]]], is passed to the block and captured by the block variables using parallel (or multiple) assignment:
i, a = h.next
#=> [1, [[1, 2], [1, 3], [1, 4]]]
i #=> 1
a #=> [[1, 2], [1, 3], [1, 4]]
As i is not used in the block calculation, it is customary to replace that block variable with the local variable _.
We can now perform the block calculation:
a.map.with_index { |i,b| [b,i] }
#=> [[0, [1, 2]], [1, [1, 3]], [2, [1, 4]]]
The remaining calculations are performed similarly.
you could try this
def func ary
ret = []
# group by first ones, and each sort by second ones
a = ary.group_by{|i| i[0]}.map{|_,i| i.sort_by{|j| j[1]}}
# add to ret
(0...a.map{|i| i.size}.max).map{
a.map{|i| ret << i.shift}
}
ret.compact
end
a = [[1, 2],[1, 3],[1, 4],[2, 3],[2, 4],[3, 4]]
p func(a)
#=> [[1, 2], [2, 3], [3, 4], [1, 3], [2, 4], [1, 4]]
Assuming the initial array is sorted by the first element:
arr =
[
[1, 2],
[1, 3],
[1, 4],
[2, 3],
[2, 4],
[3, 4],
]
res = []
arr_dup = arr.dup
remaining_values = arr_dup.map { |el| el[0] }
current_value = remaining_values.first
loop do
arr_dup.each_with_index do |el, index|
if el[0] >= current_value
res << el
current_value = remaining_values.select { |v| v > el[0] }.first || remaining_values.first
remaining_values.delete_at(remaining_values.index(current_value))
arr_dup.delete_at(index)
break
end
end
break if remaining_values.empty?
end
p arr #=> [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
p res #=> [[1, 2], [2, 3], [3, 4], [1, 3], [2, 4], [1, 4]]
Few tests:
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], [5, 1], [20, 2]] =>
[[1, 2], [2, 3], [3, 4], [5, 1], [20, 2], [1, 3], [2, 4], [1, 4]]
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], [5, 1], [5, 2], [20, 2]] =>
[[1, 2], [2, 3], [3, 4], [5, 1], [20, 2], [1, 3], [2, 4], [5, 2], [1, 4]]

Array of 28 items doesn't work. Nothing happen from compiler

I'm trying write my iOS app with static data where the data will be saved in Array. But if I'm working with 4-5 items, is it OK, if is there more than 5, the compiler doesn't work. He is on the step like you can see on this screen:
And I need the informations next the name of items. Someone know where is problem, how I can fix it?
var people = [
[1, "Breta", 3],
[2, "Brunda", 3],
[3, "Antonin", 3],
[4, "Andolf", 3],
[5, "Barborka", 2],
[6, "Boruvka", 2],
[7, "Anicka", 2],
[8, "Antonin", 3],
[9, "Andolf", 3],
[10, "Barborka", 2],
[11, "Boruvka", 2],
[12, "Anicka", 2],
[13, "Antonin", 3],
[14, "Andolf", 3],
[15, "Barborka", 2],
[16, "Boruvka", 2],
[17, "Anicka", 2],
[18, "Antonin", 3],
[19, "Andolf", 3],
[20, "Barborka", 2],
[21, "Boruvka", 2],
[22, "Anicka", 2],
[23, "Antonin", 3],
[24, "Andolf", 3],
[25, "Barborka", 2],
[26, "Boruvka", 2],
[27, "Anicka", 2],
[28, "Andulka", 2]
]
You just need to declare it as [AnyObject]:
var people:[AnyObject] = [[1, "Breta", 3],[2, "Brunda", 3],[3, "Antonin", 3],[4, "Andolf", 3],[5, "Barborka", 2],[6, "Boruvka", 2],[7, "Anicka", 2],[8, "Antonin", 3],[9, "Andolf", 3],[10, "Barborka", 2],[11, "Boruvka", 2],[12, "Anicka", 2],[13, "Antonin", 3],[14, "Andolf", 3],[15, "Barborka", 2],[16, "Boruvka", 2],[17, "Anicka", 2],[18, "Antonin", 3],[19, "Andolf", 3],[20, "Barborka", 2],[21, "Boruvka", 2],[22, "Anicka", 2],[23, "Antonin", 3],[24, "Andolf", 3],[25, "Barborka", 2],[26, "Boruvka", 2],[27, "Anicka", 2],[28, "Andulka", 2]]
If you wait long enough it will finish, you just have to deal with it right now. Swift is extremely slow, this kind of stuff should be fixed in swift 1.2.
It's in beta right now with iOS 8.3.

How can I sort this array of arrays by the second value in each array?

I have the following array:
[[1, 2], [44, 1], [18395, 3]]
Which I obtained by using this code:
current_user.friends_products.where("units.primary_image_id IS NOT NULL").group_by{|u| u.creator_id}.map {|k,v| [k, v.length]}
I want to sort the array by the second value of each array from greatest to least. So, this is what I'm trying to achieve:
[[18395, 3], [1, 2], [44, 1]]
Use #sort_by with the second element descending:
x = [[1, 2], [44, 1], [18395, 3]]
x.sort_by { |a, b| -b }
#=> [[18395, 3], [1, 2], [44, 1]]
You can use this Array#sort block:
[[1, 2], [44, 1], [18395, 3]].sort { |a, b| b[1] <=> a[1] }
# => [[18395, 3], [1, 2], [44, 1]]
[[1, 2], [44, 1], [18395, 3]].sort_by(&:last).reverse
arr =[[1, 2], [44, 1], [18395, 3]]
arr.sort_by{|x,y|y}.reverse
# => [[18395, 3], [1, 2], [44, 1]]

Sort array in Ruby on Rails

arr = [
[0, "Moving Companies", 10],
[0, "ab-thera-sensa", 5],
[0, "belt-center", 16],
[0, "isabel", 3],
[0, "kreatio", 2],
[0, "service1", 7],
[0, "sorbion-sachet-multi-star", 6],
[0, "sss", 15],
[0, "telecom-service-industry", 14],
[1, " AbsoPad", 13],
[1, "telecom-service", 8],
[2, "cutisorb-ultra", 12],
[2, "sorbion-contact", 11],
[2, "sorbion-sachet-multi-star", 9]
]
Suppose this is my array, now I want to sort it on the basis of the first element in descending order. I can do a arr.sort.reverse but the problem starts now
I get the array as :
[
[2, "sorbion-sachet-multi-star", 9],
[2, "sorbion-contact", 11],
[2, "cutisorb-ultra", 12],
[1, "telecom-service", 8],
[1, " AbsoPad", 13],
[0, "telecom-service-industry", 14],
[0, "sss", 15], [0, "sorbion-sachet-multi-star", 6],
[0, "service1", 7],
[0, "kreatio", 2],
[0, "isabel", 3],
[0, "belt-center", 16],
[0, "ab-thera-sensa", 5],
[0, "Moving Companies", 10]
]
Now the array should be sorted on the basis of the second element in ascending order.
How can that be achieved?
The result should look like :
[
[2, "cutisorb-ultra", 12],
[2, "sorbion-contact", 11],
[2, "sorbion-sachet-multi-star", 9],
[1,.......]
]
Customize the sorting with a block. First do a descending sort by the first element (0). If they are equal do instead an ascending sort by the second element (1):
arr.sort! do |a, b|
result = b[0] <=> a[0]
result = a[1] <=> b[1] if result == 0
result
end
How about this?
arr.sort { |i,j| [j[0],j[2]] <=> [i[0],i[2]] }
Outputs:
=> [[2, "cutisorb-ultra", 12],
[2, "sorbion-contact", 11],
[2, "sorbion-sachet-multi-star", 9],
[1, " AbsoPad", 13],
[1, "telecom-service", 8],
[0, "belt-center", 16],
[0, "sss", 15],
[0, "telecom-service-industry", 14],
[0, "Moving Companies", 10],
[0, "service1", 7],
[0, "sorbion-sachet-multi-star", 6],
[0, "ab-thera-sensa", 5],
[0, "isabel", 3],
[0, "kreatio", 2]]
please try:
arr.sort_by{|x|[-x[0],-x[2]]}

Resources