J'ai un tableau d'objets qui sont triés par l'un des attributs de cet objet, et je souhaite y insérer un autre objet à une position déterminée par cet attribut de l'objet.

En gros, quelque chose comme:
foo = [User(score: 10), User(score: 8), User(score: 5), User(score: 1)]
Et dans ce tableau, je veux insérer:
bar = User(score: 6)
À l'index correct, donc dans ce cas à l'index 2.

Je pourrais le pousser vers le tableau puis sort_by, mais je me demandais s'il y avait une meilleure solution pour ce problème (une sorte de méthode d'insertion où vous pouvez passer un bloc pour définir l'index).

Merci d'avance :)

1
Jeroen 4 avril 2017 à 03:08

2 réponses

Meilleure réponse

Code

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

Exemple

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

Remarque

Notez que Zelda a été inséré à la fin. Dans ce cas,

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

Donc l'index -1 a été utilisé (... || -1), ce qui signifie que la valeur doit être insérée après le dernier élément de arr. Voir String # insert.

0
Cary Swoveland 4 avril 2017 à 04:32

Vous pouvez trouver l'index, puis l'insérer si vous voulez éviter un tri complet. Quelque chose comme -

insert_index = foo.index { |x| x.score <= new_user.score } || -1
foo.insert(insert_index, new_user)
2
Rahul 5 avril 2017 à 19:24