Bagaimana cara memetakan dengan indeks di Ruby?


438

Apa cara termudah untuk mengkonversi

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

untuk

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

Jawaban:


835

Jika Anda menggunakan ruby ​​1.8.7 atau 1.9, Anda dapat menggunakan fakta bahwa metode iterator seperti each_with_index, ketika dipanggil tanpa blok, mengembalikan Enumeratorobjek, yang dapat Anda panggil Enumerablemetode seperti mappada. Jadi kamu bisa melakukan:

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

Di 1.8.6 Anda dapat melakukan:

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

Terima kasih! Bisakah Anda memberi saya petunjuk untuk dokumentasi .each_with_index.map?
— Misha Moroshko

1
@Misha: mapadalah metode Enumerableseperti biasa. each_with_index, Saat dipanggil tanpa blok, mengembalikan sebuah Enumeratorobjek (di 1.8.7+), yang campuran dalam Enumerable, sehingga Anda dapat memanggil map, select, rejectdll di atasnya seperti pada array, hash, berkisar dll
— sepp2k

9
IMO ini lebih sederhana dan lebih mudah dibaca di 1.8.7+:arr.map.with_index{ |o,i| [o,i+2] }
— Phrogz

4
@ Phrogz: map.with_indextidak berfungsi di 1.8.7 ( mapmengembalikan array ketika dipanggil tanpa blok di 1.8).
— sepp2k

2
Penting untuk dicatat ini tidak berfungsi dengan .map! jika Anda ingin secara langsung memengaruhi array yang Anda gunakan.
— Ash Blue


130

Di ruby ​​1.9.3 ada metode chainable yang disebut with_indexyang bisa dirantai untuk memetakan.

Sebagai contoh:

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

17

Kebingungan atas:

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

12
Andrew harus memiliki keamanan pekerjaan yang hebat! :)
— David J.

9

Berikut adalah dua opsi lagi untuk 1.8.6 (atau 1.9) tanpa menggunakan enumerator:

# 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

Cara yang menyenangkan, tetapi tidak berguna untuk melakukan ini:

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

Kenapa benci? Ini adalah cara yang berfungsi untuk melakukan ini DAN saya bahkan mengatakan itu adalah cara konyol untuk mencapai hasil.
— Automatico

panggilan ke #index berarti sekarang ini merupakan O (N ^ 2) loop juga mengapa +2? :)
— rogerdpack

2
Saat saya menulis A fun, but useless way. +2adalah untuk membuat output yang diminta OP
— 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 TUHAN! Apakah Anda bahkan membaca jawaban yang lain? map.with_indexsudah ada di ruby. Mengapa menyarankan untuk membuka kembali kelas enumerable dan menambahkan sesuatu yang sudah ada?
— nathanvda

Ini mungkin cara yang lebih mudah untuk menggunakan 1.8.6 dan 1.8.7 (ya beberapa dari kita masih menggunakannya) daripada harus menggunakan hal-hal aneh seperti each_with_index.mapdll. Dan bahkan kita yang pada versi yang lebih baru mungkin lebih suka daripada harus menggunakan map.with_index FWIW :)
— rogerdpack

1

Saya sering melakukan ini:

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

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

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

Alih-alih secara langsung mengulangi elemen-elemen array, Anda melakukan iterasi pada berbagai bilangan bulat dan menggunakannya sebagai indeks untuk mengambil elemen-elemen array.


1
Jika Anda membaca jawaban lain, saya harap Anda sekarang menyadari ada pendekatan yang lebih baik. Jadi tidak yakin mengapa Anda perlu menambahkan ini.
— nathanvda

Jika jawaban Andrew Grimm layak mendapat sepuluh suara, maka jawaban ini pantas setidaknya satu!
— Camille Goudeseune
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.