2017-04-04 8 views
1

Ich habe ein Array von Objekten, die nach einem der Attribute dieses Objekts sortiert sind, und ich möchte ein anderes Objekt dort an einer Position einfügen, die von diesem Attribut bestimmt wird des Objekts.In ein Array an einer bestimmten Stelle basierend auf Array-Inhalt einfügen Ruby

Im Grunde so etwas wie:
foo = [User(score: 10), User(score: 8), User(score: 5), User(score: 1)]
Und in diesem Array, mag ich einfügen:
bar = User(score: 6)
Bei dem richtigen Index, so dass in diesem Fall bei Index 2.

ich es schieben konnte an das Array und dann sort_by, aber ich frage mich, ob es eine bessere Lösung für dieses Problem gibt (eine Art von Insert-Methode, wo Sie einen Block übergeben können, um den Index zu definieren).

Vielen Dank im Voraus :)

+0

Ich denke, dass diese Lösung für Ihre Zwecke gut sein könnte: http://stackoverflow.com/questions/23481725/using-bsearch-to-find-index-for-inserting-new-element-into-sorted-array –

Antwort

0

-Code

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

Beispiel

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 

Hinweis

Beachten Sie, dass Zelda wurde am Ende eingefügt. In diesem Fall wurde

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

so der Index -1 verwendet (... || -1), was bedeutet, dass der Wert nach dem letzten Elemente der arr eingefügt werden soll. Siehe String#insert.

+1

Hey Cary, ich weiß nicht, warum du abgelehnt wirst, aber das ist die beste Antwort. Der Standardwert "-1" ist wirklich schlau, haha. Danke auch für das umfassende Beispiel. Danke für die Bemühung! Du hast mir wirklich geholfen :) – Jeroen

1

Sie Index finden können, und dann einfügen, wenn Sie eine vollständige Art vermeiden wollen. So etwas wie -

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

Dies ist in der Tat eine kluge Lösung! Das einzige Problem hier wäre, dass, wenn new_user.score immer kleiner ist als die anderen Scores, es nicht am Ende eingefügt wird, wie es sollte. Cary Swoveland gab eine ähnliche Antwort auf Ihre und fügte einen Standardwert von -1 hinzu, wenn foo.index null zurückgibt. Aber das ist definitiv der richtige Ansatz, denke ich! Danke Rahul :) – Jeroen

+0

Guter Fang. Nur bearbeitet, um diesen Fall zu berücksichtigen. – Rahul

Verwandte Themen