sorting a ruby array of objects by an attribute that could be nil
How about in Child
defining <=>
to be based on category.position
if category
exists, and sorting items without a category
as always greater than those with a category
?
class Child
# Not strictly necessary, but will define other comparisons based on <=>
include Comparable
def <=> other
return 0 if !category && !other.category
return 1 if !category
return -1 if !other.category
category.position <=> other.category.position
end
end
Then in Parent
you can just call children.sort
.
Sorting an array based on an attribute that may be nil in some elements
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]
Sort array by object properties but with nil? condition in Ruby
First, you probably want to do this sorting in your controller, or even in your model. Putting it in your view makes it a bit noisy.
Second, this solution should work for you. It's fairly short.
@users.sort_by { |u| u.startup.nil? || u.startup.blank? ? 255.chr : u.startup[0].name }
Using 255.chr
will push all empty ([]
) and null (nil
) arrays to the back of the array, as you specified in your comment that you'd like to do that. I assume that there's a cleaner way of representing 255.chr
, but I haven't been able to find one.
If a user with no startups is represented as an empty array ([]
), then you can remove u.startup.nil? ||
from that line of code. Similarly, if a user with no startups is represented as nil
, then you can remove || u.startup.blank?
from it. The code as is assumes that a user with no startups can either have an empty or null array.
Sort an array of hashes when some objects have nil attributes
Treat the nil
objects as something else, perhaps 0
or Float::INFINITY
?
search_results.sort_by { |user| user.age || 0 }
Since nil.to_i == 0
, you could also do:
search_results.sort_by { |user| user.age.to_i }
How to use sort_by with values that could be nil?
Use this syntax,
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
guarantees, 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 beginning.
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]
Source.
sorting an array of objects by attribute in ruby raises undefined method error
You need some whitespaces. Any token starting with a :
is a symbol in Ruby.
ar.sort! {|i1,i2| (i2.y ? i2.y : i2.x) <=> (i1.y ? i1.y : i1.x)}
And the last line, puts ar
is ok.
Ruby: Sort array of objects after an array of name properties
You can use Enumerable#sort_by
my_array.sort_by {|x| @sizes_sort_order.index(x.name) }
Safe sort with array key
(Note: I don't understand what you mean by "first_name
and last_name
may be false
". That doesn't sound right not me. I'm going to assume that they're potentially nil
, but not false
.)
For a quick and simple workaround, you can coerce the nil
values into String
s, for example with:
array.sort_by do |item|
if item.expression
[String(item.title), String(item.description)]
else
[String(item.first_name), String(item.last_name)]
end
end
This is almost equivalent to saying "sort alphabetically; nil
s last".
It does not distinguish between a value being ""
vs a nil
. If you want to make that aspect of the sorting stricter, you'll need to write something more custom, using the <=>
operator.
Related Topics
In Rails - Is There a Rails Method to Convert Newlines to <Br>
Problems with the Rails Console, Rvm and Readline
Ruby Hash Default Value Behavior
Rails with Ruby-Debugger Throw 'Symbol Not Found: _Ruby_Current_Thread (Loaderror)'
How to Encode Media in Base64 Given Url in Ruby
Best Way to Debug Third-Party Gems in Ruby
Warning: Constant ::Fixnum Is Deprecated When Generating New Model
How to Set Default Ruby Version with Rvm
How to Generate a Human Readable Time Range Using Ruby on Rails
Ruby Read CSV File as Utf-8 And/Or Convert Ascii-8Bit Encoding to Utf-8
Best Way to Highlight Current Page in Rails 3? - Apply a CSS Class to Links Conditionally
Bundler Cannot Install Any Gems Without Sudo
Return First Match of Ruby Regex
Ruby String to Date Conversion
Open the Default Browser in Ruby