J'ai un cours de rubis
class MyClass
attr_writer :item1, :item2
end
my_array = get_array_of_my_class() #my_array is an array of MyClass
unique_array_of_item1 = []
Je veux pousser MyClass#item1
à unique_array_of_item1
, mais seulement si unique_array_of_item1
ne contient pas encore ce item1
. Il existe une solution simple que je connais: il suffit de parcourir my_array
et de vérifier si unique_array_of_item1
contient déjà le item1
actuel ou non.
Y a-t-il une solution plus efficace?
Vous pouvez utiliser Set au lieu de Array.
@Coorasse a bonne réponse , mais il devrait l'être:
my_array | [item]
Et pour mettre à jour my_array
en place:
my_array |= [item]
Vous n'avez pas besoin de parcourir my_array
à la main.
my_array.Push(item1) unless my_array.include?(item1)
Modifier:
Comme le souligne Tombart dans son commentaire, utiliser Array#include?
n’est pas très efficace. Je dirais que l'impact sur les performances est négligeable pour les petits tableaux, mais vous pouvez vouloir utiliser Set
pour les plus grands.
Vous pouvez convertir item1 en tableau et les rejoindre:
my_array | [item1]
Il est important de garder à l'esprit que la classe Set et le | method (également appelée "Set Union") donnera un tableau d'éléments uniques , ce qui est génial si vous ne voulez pas de doublons, mais qui sera une mauvaise surprise si vous avez des éléments non uniques dans votre tableau d'origine.
Si vous ne voulez pas perdre au moins un élément dupliqué dans votre tableau d'origine, itérer dans le tableau avec un retour anticipé est le pire des cas, O (n), ce qui n'est pas si mal dans le grand schéma des choses .
class Array
def add_if_unique element
return self if include? element
Push element
end
end
Je ne sais pas si c'est la solution parfaite, mais a fonctionné pour moi:
Host_group = Array.new if not Host_group.kind_of?(Array)
Host_group.Push(Host)