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.