Ruby dizininde nasıl eşlenir?


438

Dönüştürmenin en kolay yolu nedir

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

için

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

Yanıtlar:


835

Ruby 1.8.7 veya 1.9 kullanıyorsanız, yineleyici yöntemlerinin each_with_index, blok olmadan çağrıldığında, gibi yöntemleri Enumeratorçağırabileceğiniz bir nesneyi döndürme Enumerablegibi kullanabilirsiniz map. Böylece şunları yapabilirsiniz:

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

1.8.6'da şunları yapabilirsiniz:

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

Teşekkürler! Bana belgelere bir işaretçi verebilir misiniz .each_with_index.map?
Misha Moroshko

1
@Misha: her zamanki gibi mapbir yöntemdir Enumerable. each_with_indexBir bloğun olmadan çağrıldığında, bir döner Enumeratorhangi karışımlar, (1.8.7+ olarak) nesneyi Enumerablearamak, böylece map, select, rejectsadece bir dizi, karma olduğu gibi, üzerinde vs., vs. aralığı
sepp2k

9
IMO bu 1.8.7+ daha basit ve daha iyi okuma:arr.map.with_index{ |o,i| [o,i+2] }
Phrogz

4
@Phrogz: map.with_index1.8.7'de çalışmaz ( map1.8'de blok olmadan çağrıldığında bir dizi döndürür).
sepp2k

2
Bunun .map ile çalışmadığını unutmayın. döngü yaptığınız diziyi doğrudan etkilemek istiyorsanız.
Ash Blue


130

Yakut 1.9.3'te with_indexharitaya zincirlenebilecek zincirlenebilir bir yöntem vardır .

Örneğin:

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

17

Üst şaşkınlık üzerinde:

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

12
Andrew harika bir iş güvenliğine sahip olmalı! :)
David

9

Numaralandırıcı kullanmadan 1.8.6 (veya 1.9) için iki seçenek daha:

# 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

Bunu yapmanın eğlenceli ama faydasız bir yolu:

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

Neden nefret? Bunu yapmanın işlevsel bir yolu VE hatta sonuçlara ulaşmak için aptalca bir yol olduğunu bile söylüyorum.
Automatico

#index çağrısı, bunun artık bir O (N ^ 2) döngüsü olduğu anlamına gelir, ayrıca neden +2? :)
rogerdpack

2
Yazarken A fun, but useless way. +2OP'nin istediği çıktıyı yaratmak
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
AMAN TANRIM! Diğer cevapları bile okudun mu? map.with_indexzaten yakutta var. Numaralandırılabilir sınıfı yeniden açmayı ve zaten var olan bir şeyi eklemeyi neden önerirsiniz?
nathanvda

Bu, each_with_index.mapvb. Gibi garip şeyler kullanmak zorunda kalmak yerine 1.8.6 ve 1.8.7 (evet bazılarımız hala kullanıyor) için daha kolay bir yol olabilir ve daha yeni sürümlerde olanlarımız bile kullanmayı tercih edebilir map.with_index FWIW :)
rogerdpack

1

Bunu sık sık yaparım:

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

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

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

Dizinin öğeleri üzerinde doğrudan yineleme yapmak yerine, bir dizi tamsayı üzerinde yineleme yapıyor ve bunları dizinin öğelerini almak için dizinler olarak kullanıyorsunuz.


1
Diğer cevapları okursanız, umarım şimdi daha iyi yaklaşımlar olduğunu fark edersiniz. Bunu neden eklemeniz gerektiğinden emin değilsiniz.
nathanvda

Andrew Grimm'in cevabı on oyu hak ediyorsa, o zaman bu en az bir oyu hak ediyor!
Camille Goudeseune
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.