2017-04-04 77 views
1

我有一个对象数组,它按照此对象的一个​​属性进行排序,并且我想在该位置插入另一个对象,该位置由该属性确定的对象。基于数组内容在特定位置插入数组Ruby

基本上是这样的:
foo = [User(score: 10), User(score: 8), User(score: 5), User(score: 1)]
这阵中,我想插入:
bar = User(score: 6)
在正确的索引,所以在这种情况下,在指数2

我能推到数组,然后sort_by,但我想知道是否有更好的解决方案(这种问题可以通过块来定义索引的某种插入方法)。

在此先感谢:)

+0

我认为这个解决方案可能适合您的目的:http://stackoverflow.com/questions/23481725/using-bsearch-to-find-index-for-inserting-new-element-into-sorted-array –

回答

0

代码

def insert_new(arr, new_instance) 
    arr.insert(arr.index { |instance| new_instance.score >= instance.score } || -1, 
    new_instance) 
end 

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 

注意

注意,塞尔达被插入到最后。在这种情况下,

arr.index { |instance| new_instance.score >= instance.score } #=> nil 

所以索引-1使用(... || -1),这意味着该值是arr的最后一个元素之后插入。见String#insert

+1

嘿卡里,我不知道你为什么被低估,但这是最好的答案。默认的'-1'真的很聪明,哈哈。谢谢你的全面的例子。感谢您的努力!你真的帮助我:) – Jeroen

1

你可以找到索引,然后插入,如果你想避免完整的排序。喜欢的东西 -

insert_index = foo.index { |x| x.score <= new_user.score } || -1 
foo.insert(insert_index, new_user) 
+1

这确实是一个聪明的解决方案!这里唯一的问题是,如果new_user.score总是小于其他分数,它不会像它应该插入的那样结束。 Cary Swoveland给了你一个类似的答案,如果foo.index返回nil,他添加了默认值-1。 但我认为这绝对是正确的做法!谢谢Rahul :) – Jeroen

+0

好的。刚刚编辑来解释这种情况。 – Rahul