2017-05-17 7 views
1

In Ruby 2.4, wie finde ich den frühesten Index eines Elements eines Arrays in einem anderen Array? Das heißt, wenn irgendein Element eines Arrays in dem anderen Array auftritt, möchte ich den ersten Index erhalten. Ich dachte, find_index könnte es tun, aberIn Ruby wie finde ich den Index eines Elements aus einem Array?

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 

Im obigen Beispiel würde ich erwarten, dass die Ausgabe „1“, weil das Element „b“ tritt bei Index 1 im Array „a“ ​​zu sehen.

+0

Sie haben 'a.find_index ("a")' den Index ' "a" zu finden' in '[ "a", "b", "c" ] ', also warum machst du' a.find_index (["b", "c"]) 'und nicht' a.find_index ("b") ', um den Index von' "b" 'zu finden? Der 'a.find_index ([" b "," c "])' sucht nach einem Element im Array 'a', das wie '["b", "c"] 'aussieht, was nicht vorhanden ist. Das ist ein Sub-Array, kein Element. – lurker

+0

Versuchen Sie, das erste Vorkommen von 'b, c' sequenziell oder einfach den ersten Eintrag im angegebenen Array zu finden? – tadman

Antwort

1

find_index nimmt ein einzelnes Element. Sie könnten das Minimum finden, indem Sie so etwas wie

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

@CarySwoveland keine echte Meinung zu 'compact'; Ich sehe es oft benutzt und es scheint mir klar genug zu sein. Außerdem gibt fyi '[nil, nil, nil] .compact.min'' nil' zurück. Also keine Ausnahme. –

+0

Ich stehe korrigiert. Vielen Dank. Da es sich um einen Fehler handelte, habe ich meinen früheren Kommentar gelöscht. –

0

Sie können find_index verwenden und den benötigten Wert aus dem Array übergeben:

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

Sie können map verwenden jedes Element in Ihrem a Array zu bekommen und dann den Index zu erhalten, die jedes Element entsprechen:

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

Eine andere Möglichkeit, es zu handhaben könnte die Enumerable#each_with_index zu benutzen:

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

Wenn Sie die Indizes für jedes Element in ["b", "c"] mit dem ["a", "b", "c"] Array überprüfen möchten, können Sie die erste Karte, die Array-Werte erhalten, und dann die a,b,c verwenden, um die Indizes zu überprüfen:

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

Sie können auch Array#index und Enumerable#find_index sehen.

+1

Und der Downvote, warum? Ich bin hier um zu lernen. –

+0

Jemand ist launisch. Ich habe mich dafür entschieden, das Gleichgewicht im Universum wiederherzustellen. Ich denke es liegt daran, dass es nicht mit einem Array angesprochen wird. – tadman

+0

Die Fragen erfordern, dass eine einzelne Zahl (ein Index) zurückgegeben wird, die möglicherweise in nachfolgenden Berechnungen verwendet wird. Du hast das nicht getan. Ich nehme an, das ist der Grund für den Downvote. Auch, a.map {| e | a.find_index (e)} 'hat keinen Wert. –

5

tun Sie Array#index mit einem Block verwenden können.

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

Zitat aus dem Text & Tabellen:

Wenn ein Block anstelle ein Argument angegeben wird, gibt den Index des ersten Objekts, für die der Block true zurück. Gibt null zurück, wenn keine Übereinstimmung gefunden wird.


Als Cary in seinem Kommentar darauf hingewiesen, ist es nicht der performant Algorithmus alle Elemente in a gegen alle Elemente in ['b', 'c'] vergleichen (dies O(n*m) führen würde). Abhängig von der Größe beider Arrays könnte es sinnvoll sein, zuerst eine effizientere Datenstruktur zu erstellen. ein Set statt ein Array hat einige Kosten für die set vorne schaffen, sondern macht den Vergleich im Block viel schneller (Gesamt O(n+m)):

require 'set' 

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

Wenn 'b = ['b', 'c']', ist dies vorzuziehen, um 'b' aufzuspüren, um nach Übereinstimmungen in' a' zu suchen. Wenn "a" und "b" jeweils "n" und "m" Elemente enthalten, und das Element am Index "i" von "a" ist das erste Element, das mit einem Element von "b" übereinstimmt ("i <= n") "i * m" Operationen sind erforderlich. Wenn "b" aufgezählt ist, sind "n * m" -Operationen erforderlich. Dies ist daher schneller als das Aufzählen von "b" unabhängig von "n" und "m". Wenn "n * m" groß ist, würde ich vorschlagen, zuerst zu berechnen 'require set; sb = b.to_set' und verwenden Sie 'sb.include? (x)', um diese Operation zu beschleunigen. –

0

Sie eine Übersicht über alle Elemente des Arrays b in dem finden konnte Array a, und finden Sie den Index min, um den Index zu finden, bei dem ein Element aus Array b zuerst in Array a aufgetreten ist.

So etwas wie unten:

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

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