Reputation: 33
I have an array of objects that are sorted by one of the attributes of this object, and I want to insert another object in there at a position that is determined by that attribute of the object.
Basically, something like:
foo = [User(score: 10), User(score: 8), User(score: 5), User(score: 1)]
And in that array, I want to insert:
bar = User(score: 6)
At the correct index, so in this case at index 2.
I could push it to the array and then sort_by
, but I was wondering if there is a better solution for this problem (some kind of insert method where you can pass a block to define the index).
Thanks in advance :)
Upvotes: 2
Views: 6067
Reputation: 1505
You could find index and then insert if you wanna avoid a full sort. Something like -
insert_index = foo.index { |x| x.score <= new_user.score } || -1
foo.insert(insert_index, new_user)
Upvotes: 2
Reputation: 110675
Code
def insert_new(arr, new_instance)
arr.insert(arr.index { |instance| new_instance.score >= instance.score } || -1,
new_instance)
end
Example
class A
def initialize(user, score)
@user, @score = user, score
end
end
arr = [A.new("Hank", 10), A.new("Lois", 8), A.new("Billy-Bob", 6),
A.new("Trixy", 4)]
#=> [#<A:0x007fad7b02fd70 @user="Hank", @score=10>,
# #<A:0x007fad7b02fcf8 @user="Lois", @score=8>,
# #<A:0x007fad7b02fc80 @user="Billy-Bob", @score=6>,
# #<A:0x007fad7b02fbe0 @user="Trixy", @score=4>]
insert_new(arr, A.new("Hubert", 7))
#=> [#<A:0x007fad7a027450 @user="Hank", @score=10>,
# #<A:0x007fad7a0273b0 @user="Lois", @score=8>,
# #<A:0x007fad7a850b90 @user="Hubert", @score=7>,
# #<A:0x007fad7a027310 @user="Billy-Bob", @score=6>,
# #<A:0x007fad7a027270 @user="Trixy", @score=4>]
insert_new(arr, A.new("Zelda", 2))
#=> [#<A:0x007fad7a027450 @user="Hank", @score=10>,
# #<A:0x007fad7a0273b0 @user="Lois", @score=8>,
# #<A:0x007fad7a850b90 @user="Hubert", @score=7>,
# #<A:0x007fad7a027310 @user="Billy-Bob", @score=6>,
# #<A:0x007fad7a027270 @user="Trixy", @score=4>,
# #<A:0x007fad7b876128 @user="Zelda", @score=2>]
insert_new(arr, A.new("Slim", 8))
# Slim is inserted between Hank and Lois
insert_new(arr, A.new("Rhonda", 8))
# Rhonda is inserted between Hank and Slim
Note
Notice that Zelda was inserted at the end. In that case,
arr.index { |instance| new_instance.score >= instance.score } #=> nil
so the index -1
was used (... || -1
), meaning that the value is to be inserted after the last element of arr
. See String#insert.
Upvotes: 3