snippetrubyMinor
Sort array of hashes with nil values last
Viewed 0 times
lastarraywithnilhashesvaluessort
Problem
I wrote a method which sorts an array of hashes by given hash keys. The method should put
My solution looks quite complex. Is there a better way to achieve the ordering in Ruby?
nil values at the end.def sort(records, *attrs)
records.sort do |a,b|
result = 0
attrs.each do |attr|
unless a[attr] == b[attr]
result = if a[attr].nil?
1
elsif b[attr].nil?
-1
else
a[attr] b[attr]
end
break
end
end
result
end
end
p sort([{:a => 1},{:a => nil},{:a => 2}], :a)
#=> [{:a=>1}, {:a=>2}, {:a=>nil}]
p sort([{:a => nil},{:a => 'x'},{:a => 'a'}], :a)
#=> [{:a=>"a"}, {:a=>"x"}, {:a=>nil}]My solution looks quite complex. Is there a better way to achieve the ordering in Ruby?
Solution
Set Unions
Looking at your code, when you loop through the attrs, you are breaking after you find the first key that is in
Shorthand if/elseif syntax
You can use the keyword
Putting it all together
Looking at your code, when you loop through the attrs, you are breaking after you find the first key that is in
a and in b and in the passed attrs. This is also known as the union of the arrays. As such you can simplify the inner loop with:(attrs & a.keys & b.keys).firstShorthand if/elseif syntax
You can use the keyword
then in conjunction with if and elsif to cut down on the whitespace of your if-eslif chain. The syntax would look like:if attr.nil? then 0
elsif a[attr].nil? then 1
elsif b[attr].nil? then -1
else a[attr] b[attr] endPutting it all together
def sort(records, *attrs)
records.sort do |a, b|
attr = (attrs & a.keys & b.keys).first
if attr.nil? then 0
elsif a[attr].nil? then 1
elsif b[attr].nil? then -1
else a[attr] b[attr] end
end
endCode Snippets
(attrs & a.keys & b.keys).firstif attr.nil? then 0
elsif a[attr].nil? then 1
elsif b[attr].nil? then -1
else a[attr] <=> b[attr] enddef sort(records, *attrs)
records.sort do |a, b|
attr = (attrs & a.keys & b.keys).first
if attr.nil? then 0
elsif a[attr].nil? then 1
elsif b[attr].nil? then -1
else a[attr] <=> b[attr] end
end
endContext
StackExchange Code Review Q#128089, answer score: 4
Revisions (0)
No revisions yet.