2017-05-17 1 views
1

Dans Ruby 2.4, comment trouver l'index le plus tôt d'un élément d'un tableau dans un autre tableau? C'est-à-dire, si un élément d'un tableau se produit dans l'autre tableau, je veux obtenir le premier index. Je pensais que find_index pourrait le faire, maisDans Ruby, comment trouver l'index d'un tableau d'éléments?

2.4.0 :004 > a = ["a", "b", "c"] 
=> ["a", "b", "c"] 
2.4.0 :005 > a.find_index("a") 
=> 0 
2.4.0 :006 > a.find_index(["b", "c"]) 
=> nil 

Dans l'exemple ci-dessus, j'attendre à la sortie « 1 » parce que l'élément « b » se produit à l'index 1 dans le tableau « a ».

+0

Vous avez 'a.find_index ("a")' trouver l'indice de ' "un"' 'dans [ "a", "b", "c" ] ', alors pourquoi faites-vous' a.find_index (["b", "c"]) 'et non' a.find_index ("b") 'pour trouver l'index de' "b" '? Le 'a.find_index ([" b "," c "])' cherche un élément dans le tableau 'a' qui ressemble à' ["b", "c"] 'qui n'est pas là. C'est un sous-tableau, pas un élément. – lurker

+0

Essayez-vous de trouver la première occurrence de 'b, c' séquentiellement, ou simplement la première entrée dans le tableau donné? – tadman

Répondre

1

find_index prend un seul élément. Vous pouvez trouver le minimum en faisant quelque chose comme

a = ["a", "b", "c"] 
to_find = ["b", "c"] 
to_find.map {|i| a.find_index(i) } .compact.min # => 1 
+0

@CarySwoveland pas de véritable opinion sur 'compact'; Je le vois assez souvent et cela me semble assez clair. De plus, fyi '[nil, nil, nil] .compact.min' renvoie' nil'. Donc pas d'exception afaict. –

+0

Je suis corrigé. Je vous remercie. Comme c'était par erreur, j'ai supprimé mon commentaire précédent. –

0

Vous pouvez utiliser find_index et passer la valeur nécessaire à partir du tableau:

a = ["a", "b", "c"] 
p a.find_index('a') 
p a.find_index('b') 
p a.find_index('c') 
# => 0 
# => 1 
# => 2 

Vous pouvez utiliser map pour obtenir tous les éléments à l'intérieur de votre tableau a puis pour obtenir l'index correspondant à chaque élément:

p a.map{|e| a.find_index(e)} 
# => [0, 1, 2] 

Une autre façon possible de le manipuler pourrait être d'utiliser le Enumerable#each_with_index:

a.each_with_index{|e,i| puts "Element: #{e}, Index: #{i}"} 
# => Element: a, Index: 0 
# => Element: b, Index: 1 
# => Element: c, Index: 2 

Si vous voulez vérifier les index pour chaque élément ["b", "c"] à l'aide du tableau ["a", "b", "c"], vous pouvez mapper le premier, obtenir les valeurs de tableau, puis utilisez la a,b,c pour vérifier ces indices:

p ["b", "c"].map{|e| ["a", "b", "c"].find_index(e) } 
# => [1, 2] 

Vous pouvez également voir Array#index et Enumerable#find_index.

+1

Et le downvote, pourquoi? Je suis ici pour apprendre. –

+0

Quelqu'un est grincheux. J'ai voté pour rétablir l'équilibre dans l'univers. Je pense que c'est parce qu'il ne traite pas de l'appeler avec un tableau. – tadman

+0

Les questions demandent un seul nombre (un index) à retourner, éventuellement à utiliser dans les calculs ultérieurs. Tu n'as pas fait ça. Je m'attends à ce que ce soit la raison du downvote. Aussi, 'a.map {| e | a.find_index (e)} 'n'a aucune valeur. –

5

Vous pouvez utiliser Array#index avec un bloc.

a = ['a', 'b', 'c'] 
a.index { |x| ['b', 'c'].include?(x) } 
#=> 1 

Citation de la documentation:

Si un bloc est donnée au lieu d'un argument, renvoie l'index du premier objet pour lequel le bloc renvoie true. Retourne zéro si aucune correspondance n'est trouvée.


Comme Cary a souligné dans son commentaire, il n'est pas l'algorithme le plus performant pour comparer tous les éléments en a contre tout élément ['b', 'c'] (ce qui conduirait à O(n*m)). En fonction de la taille des deux baies, il peut être utile de créer une structure de données plus efficace en premier. L'utilisation d'un Set au lieu d'un tableau a un coût dans la création du set avant, mais fait la comparaison dans le bloc beaucoup plus rapide (globale O(n+m)):

require 'set' 

a = ['a', 'b', 'c'] 
set = Set.new(['b', 'c']) 
a.index { |x| set.include?(x) } 
#=> 1 
+0

Si 'b = ['b', 'c']', cela est préférable à l'énumération de 'b' recherchant des correspondances dans' a'. Si 'a' et' b' contiennent respectivement les éléments 'n' et' m', l'élément à l'index 'i' de' a' est le premier à correspondre à un élément de 'b' (' i <= n') , les opérations 'i * m' sont obligatoires. Si 'b' est énuméré, les opérations' n * m' sont requises. Ceci est donc plus rapide que l'énumération de 'b' indépendamment de' n' et 'm'. Si 'n * m' est grand, je suggérerais d'abord de' require set; sb = b.to_set', et en utilisant 'sb.include? (x)' pour accélérer cette opération. –

0

Vous pouvez trouver index de tous les éléments du tableau b dans la tableau a, et recherchez l'index min pour trouver l'index auquel un élément du tableau b s'est produit en premier dans le tableau a.

Quelque chose comme ci-dessous:

a = ["a", "b", "c"] 
b = ["b", "c"] 

b.map { |x| a.find_index(x) }.min 
#=> 1