Wie ordne ich mit Index in Ruby zu?


438

Was ist der einfachste Weg zu konvertieren

[x1, x2, x3, ... , xN]

zu

[[x1, 2], [x2, 3], [x3, 4], ... , [xN, N+1]]

Antworten:


835

Wenn Sie Ruby 1.8.7 oder 1.9 verwenden, können Sie die Tatsache verwenden, dass Iteratormethoden wie each_with_index, wenn sie ohne Block aufgerufen werden, ein EnumeratorObjekt zurückgeben, das Sie EnumerableMethoden wie mapon aufrufen können . So können Sie tun:

arr.each_with_index.map { |x,i| [x, i+2] }

In 1.8.6 können Sie Folgendes tun:

require 'enumerator'
arr.enum_for(:each_with_index).map { |x,i| [x, i+2] }

Vielen Dank! Können Sie mir einen Hinweis auf die Dokumentation geben .each_with_index.map?
Mischa Moroshko

1
@ Mischa: mapist eine Methode Enumerablewie immer. each_with_index, Wenn sie ohne einen Block aufgerufen wird , gibt ein EnumeratorObjekt (in 1.8.7+), die Mischungen in Enumerable, so können Sie anrufen map, select, rejectusw. auf sie wie auf einem Array, Hash, Reichweite usw.
sepp2k

9
IMO dies ist einfacher und besser zu lesen in 1.8.7+:arr.map.with_index{ |o,i| [o,i+2] }
Phrogz

4
@Phrogz: map.with_indexfunktioniert in 1.8.7 nicht ( mapgibt ein Array zurück, wenn es in 1.8 ohne Block aufgerufen wird).
sepp2k

2
Es ist wichtig zu beachten, dass dies mit .map nicht funktioniert! Wenn Sie das Array, auf dem Sie sich befinden, direkt beeinflussen möchten.
Ash Blue


130

In Ruby 1.9.3 gibt es eine verkettbare Methode, with_indexdie mit der Karte verkettet werden kann.

Zum Beispiel:

array.map.with_index { |item, index| ... }

17

Übertriebene Verschleierung:

arr = ('a'..'g').to_a
indexes = arr.each_index.map(&2.method(:+))
arr.zip(indexes)

12
Andrew muss eine gute Arbeitsplatzsicherheit haben! :)
David J.

9

Hier sind zwei weitere Optionen für 1.8.6 (oder 1.9) ohne Verwendung des Enumerators:

# Fun with functional
arr = ('a'..'g').to_a
arr.zip( (2..(arr.length+2)).to_a )
#=> [["a", 2], ["b", 3], ["c", 4], ["d", 5], ["e", 6], ["f", 7], ["g", 8]]

# The simplest
n = 1
arr.map{ |c| [c, n+=1 ] }
#=> [["a", 2], ["b", 3], ["c", 4], ["d", 5], ["e", 6], ["f", 7], ["g", 8]]


4

Ein lustiger, aber nutzloser Weg, dies zu tun:

az  = ('a'..'z').to_a
azz = az.map{|e| [e, az.index(e)+2]}

Warum der Hass? Es ist ein funktionierender Weg, dies zu tun UND ich sage sogar, dass dies ein dummer Weg ist, um die Ergebnisse zu erzielen.
Automatico

Der Aufruf von #index bedeutet, dass dies jetzt eine O (N ^ 2) -Schleife ist. Warum auch die +2? :)
Rogerdpack

2
Wie ich schreibe A fun, but useless way. +2ist die Ausgabe zu erstellen, die das OP verlangt
Automatico


1
module Enumerable
  def map_with_index(&block)
    i = 0
    self.map { |val|
      val = block.call(val, i)
      i += 1
      val
    }
  end
end

["foo", "bar"].map_with_index {|item, index| [item, index] } => [["foo", 0], ["bar", 1]]

3
OH MEIN GOTT! Hast du überhaupt die anderen Antworten gelesen? map.with_indexexistiert bereits in rubin. Warum sollten Sie vorschlagen, die aufzählbare Klasse erneut zu öffnen und etwas hinzuzufügen, das bereits vorhanden ist?
Nathanvda

Dies könnte ein einfacherer Weg für 1.8.6 und 1.8.7 sein (ja, einige von uns verwenden es immer noch), anstatt seltsamere Dinge wie each_with_index.mapusw. verwenden zu müssen, und selbst diejenigen von uns in neueren Versionen ziehen es möglicherweise vor, es zu verwenden map.with_index FWIW :)
Rogerdpack

1

Ich mache das oft:

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

(0...arr.length).map do |int|
  [arr[int], int + 2]
end

#=> [["a", 2], ["b", 3], ["c", 4]]

Anstatt direkt über die Elemente des Arrays zu iterieren, iterieren Sie über einen Bereich von Ganzzahlen und verwenden sie als Indizes, um die Elemente des Arrays abzurufen.


1
Wenn Sie die anderen Antworten lesen, hoffe ich, dass Sie jetzt erkennen, dass es bessere Ansätze gibt. Ich bin mir also nicht sicher, warum Sie dies hinzufügen mussten.
Nathanvda

Wenn Andrew Grimms Antwort zehn Stimmen verdient, dann verdient diese mindestens eine!
Camille Goudeseune
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.