Reputation: 2298
Please your help. I have the input_array with 3 groups of values.
The group order I need is:
1st group: Pou
2nd group: Apl
3rd group: Gab
This order is already done in input_array, but I want to sort ascending each group.
The script I have so far produces the output given in central column of table below (current output).
input_arr = ["Pou-12","Pou-7","Pou-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2","Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-4","Gab-1","Gab-2"]
b=input_arr.sort_by do |s|
if s =~ /^\d+$/
[2, $&.to_i]
else
[1, s]
end
end
puts b
and the desired sorted output array is shown below too.
input array | current output | desired output array
Pou-12 | Apl | Pou-1
Pou-7 | Gab-1 | Pou-2
Pou-4 | Gab-2 | Pou-3
Pou-8 | Gab-3 | Pou-4
Pou-9 | Gab-4 | Pou-5
Pou-11 | Gab-5 | Pou-6
Pou-10 | Pou-1 | Pou-7
Pou-3 | Pou-10 | Pou-8
Pou-2 | Pou-11 | Pou-9
Pou-1 | Pou-12 | Pou-10
Pou-6 | Pou-2 | Pou-11
Pou-5 | Pou-3 | Pou-12
Apl | Pou-4 | Apl
Gab-3 | Pou-5 | Gab-1
Gab-5 | Pou-6 | Gab-2
Gab-4 | Pou-7 | Gab-3
Gab-1 | Pou-8 | Gab-4
Gab-2 | Pou-9 | Gab-5
UPDATE
Cary's solution with array instead of hash.
a = ["Pou-7","Pou-4","Gab-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2","Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-1","Pou-12","Gab-2"]
order = [ "Pou", "Apl", "Gab" ]
a.map{ |s| head,tail = s.split("-"); [order.index(head), tail.to_i, s]}.sort.map(&:last)
=> ["Pou-1", "Pou-2", "Pou-3", "Pou-4", "Pou-5", "Pou-6", "Pou-7", "Pou-8", "Pou-9",
"Pou-10", "Pou-11", "Pou-12", "Apl", "Gab-1", "Gab-2", "Gab-3", "Gab-4", "Gab-5"]
Upvotes: 2
Views: 885
Reputation: 110725
a = ["Pou-12","Pou-7","Pou-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2",
"Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-4","Gab-1","Gab-2"]
order = { "Pou"=>0, "Apl"=>1, "Gab"=>2 }
a.map do |s|
head, tail = s.split('-')
[order[head], tail.to_i, s]
end.sort.map(&:last)
#=> ["Pou-1", "Pou-2", "Pou-3", "Pou-4", "Pou-5", "Pou-6", "Pou-7", "Pou-8", "Pou-9",
# "Pou-10", "Pou-11", "Pou-12", "Apl, "Gab-1", "Gab-2", "Gab-3", "Gab-4", "Gab-5"]
Note that head, tail = "Apl".split('-') #=> ["Apl"]
, so head #=> "Apl"
and tail #=> nil
, but then tail.to_i #=> nil.to_i #=> 0
.
See Array#<=> to understand how arrays are compared when sorting.
Upvotes: 2
Reputation: 2345
You can try this:
b = input_arr.group_by { |e| e.split("-")[0] }
b = b.flat_map { |k, v| v.sort_by!{ |vs| vs.split("-")[1].to_i }; v }
Upvotes: 2
Reputation: 4261
Your initial array looks like:
a = ["Pou-12","Pou-7","Pou-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2","Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-4","Gab-1","Gab-2"]
d = []
Group the array by it's first part:
c = a.group_by{|b| b.split("-").first}
#=> {"Pou"=>["Pou-12", "Pou-7", "Pou-4", "Pou-8", "Pou-9", "Pou-11",
#=> "Pou-10", "Pou-3", "Pou-2", "Pou-1", "Pou-6", "Pou-5"],
#=> "Apl"=>["Apl"],
#=> "Gab"=>["Gab-3", "Gab-5", "Gab-4", "Gab-1", "Gab-2"]
#=> }
Now, sort the grouped array individually:
c.each do |k, v|
d << v.sort{|b, c| ( b.split("-").last.to_i <=> c.split("-").last.to_i )}
end
Finally, since the output is Array of Array, you flatten it:
d.flatten!
#=> ["Pou-1", "Pou-2", "Pou-3", "Pou-4", "Pou-5", "Pou-6", "Pou-7", "Pou-8", "Pou-9", "Pou-10", "Pou-11", "Pou-12", "Apl", "Gab-1", "Gab-2", "Gab-3", "Gab-4", "Gab-5"]
Upvotes: 1
Reputation: 4523
input = ["Pou-12","Pou-7","Pou-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2","Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-4","Gab-1","Gab-2"]
grouped_by_prefix = input.group_by do |item|
item.split('-')[0]
end
grouped_by_prefix.each do |_, values|
values.sort_by! { |value| value.split('-')[1].to_i }
end
['Pou', 'Apl', 'Gab'].reduce([]) do |memo, key|
memo + (grouped_by_prefix[key] || [])
end
algorithm is not super efficient (for example double split
operation) but quite simple to understand
Upvotes: 2