Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting an array based on an attribute that may be nil in some elements

Tags:

I have an array of objects

[<#a star=1  val=1>, <#a star=nil val=3> , <#a star=2  val=2>] 

i need the array to be sorted by time, then by val

[ <#a star=2  val=2>, <#a star=1  val=1>, <#a star=nil val=3> ] 

but using the sort_by throws an error because the time is nil.

I am using an ugly way to sort right now, but i am sure there is a nice way to go about it

starred=[] @answers.each {|a| (starred << a) if a.starred } @answers=@answers-starred starred=starred.sort_by {|a| a.starred }.reverse @answers=starred+@answers 
like image 364
meow Avatar asked Dec 18 '10 00:12

meow


People also ask

Is empty array nil in Ruby?

nil? will only return true if the object itself is nil. That means that an empty string is NOT nil and an empty array is NOT nil. Neither is something that is false nil. => NilClassnil.

Can you sort elements in a Ruby hash object?

You can use the sort method on an array, hash, or another Enumerable object & you'll get the default sorting behavior (sort based on <=> operator) You can use sort with a block, and two block arguments, to define how one object is different than another (block should return 1, 0, or -1)

How to sort array of objects in Ruby?

The Ruby sort method works by comparing elements of a collection using their <=> operator (more about that in a second), using the quicksort algorithm. You can also pass it an optional block if you want to do some custom sorting. The block receives two parameters for you to specify how they should be compared.


1 Answers

starred.sort_by { |a| [a ? 1 : 0, a] } 

When it has to compare two elements, it compares an arrays. When Ruby compares arrays (calls === method), it compares 1st element, and goes to the 2nd elements only if the 1st are equal. ? 1 : 0 garantees, that we'll have Fixnum as 1st element, so it should be no error.

If you do ? 0 : 1, nil will appear at the end of array instead of begining.
Here is an example:

irb> [2, 5, 1, nil, 7, 3, nil, nil, 4, 6].sort_by { |i| [i ? 1 : 0, i] } => [nil, nil, nil, 1, 2, 3, 4, 5, 6, 7]  irb> [2, 5, 1, nil, 7, 3, nil, nil, 4, 6].sort_by { |i| [i ? 0 : 1, i] } => [1, 2, 3, 4, 5, 6, 7, nil, nil, nil] 
like image 175
Nakilon Avatar answered Nov 19 '22 22:11

Nakilon