2011-01-15 8 views

Odpowiedz

685

Jeśli używasz Ruby 1.8.7 lub 1.9, można skorzystać z faktu, że metody iteracyjnej jak each_with_index, gdy wywołana bez blok, zwróć obiekt Enumerator, który możesz wywołać na Enumerable metodach takich jak map. Więc można zrobić:

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

W 1.8.6 można zrobić:

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

Dzięki! Czy możesz dać mi wskaźnik do dokumentacji dla '.each_with_index.map'? –

+0

W takim przypadku 'map' jest funkcją czego? –

+1

@Misha: 'map' to jak zwykle metoda' Enumerable'. 'each_with_index', po wywołaniu bez bloku, zwraca obiekt' Enumerator' (w wersji 1.8.7+), który miksuje w 'Enumerable', dzięki czemu możesz wywołać' map', 'select',' reject' itp. tak jak na tablicy, haszym, zasięgu itp. – sepp2k

9

Oto dwie kolejne opcje 1.8.6 (lub 1.9) bez użycia wyliczający:

# 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]] 
14

Over the top zaciemnianie:

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

Podoba mi się ten jeden, niejasny kod jest zawsze zabawny w utrzymaniu. –

+9

Andrew musi mieć świetną ochronę pracy! :) –

203

Ruby> = 1.9.3 ma Enumerator#with_index(offset = 0). Aby przekonwertować tablicę do wyliczający, użyj Object#to_enum lub Array#map, co czuje się bardziej deklaratywny wam:

[:a, :b, :c].map.with_index(2).to_a 
#=> [[:a, 2], [:b, 3], [:c, 4]] 
+7

To jest najlepsza odpowiedź do tej pory! –

+3

Bardzo eleganckie rozwiązanie, dzięki! – dolzenko

+8

Wierzę, że to jest lepsza odpowiedź, ponieważ będzie działać z mapą! 'foo = ['d'] * 5; foo.map! .with_index {| x, i | x * i}; foo # => ["", "d", "dd", "ddd", "dddd"] ' –

3
a = [1, 2, 3] 
p [a, (2...a.size+2).to_a].transpose 
2
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

OMG! Czy przeczytałeś jeszcze inne odpowiedzi? 'map.with_index' już istnieje w ruby. Po co proponować ponowne otwarcie klasy przeliczalnej i dodać coś, co już istnieje? – nathanvda

+0

To może być łatwiejszy sposób, aby przejść do wersji 1.8.6 i 1.8.7 (tak, niektórzy z nas nadal go używają) zamiast używać dziwniejszych rzeczy, takich jak 'each_with_index.map' itd., A nawet ci z nas w nowszych wersjach mogą wolę używać map.with_index FWIW :) – rogerdpack

1

I często to zrobić:

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

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

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

Zamiast bezpośrednio kolejno po elementy tablicy, iterujesz na zakresie liczb całkowitych i używasz ich jako indeksów do pobierania elementów tablicy.

+1

Jeśli czytasz inne odpowiedzi, mam nadzieję, że teraz zdajesz sobie sprawę, że istnieją lepsze podejścia. Więc nie wiesz, dlaczego musisz to dodać. – nathanvda

+0

Jeśli odpowiedź Andrew Grimm zasługuje na dziesięć głosów, to ta zasługuje na co najmniej jedną! –

+0

Myślę, że powinieneś wrzucić pętlę for na dobrą miarę;) –

0

zabawy, ale bezużyteczny sposobem, aby to zrobić:

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

Dlaczego nienawiść? Jest to funkcjonujący sposób robienia tego, a nawet mówię, że to głupi sposób na osiągnięcie rezultatów. – Automatico

+0

wywołanie #index oznacza, że ​​jest to teraz pętla O (N^2), także dlaczego +2? :) – rogerdpack

+1

Kiedy piszę "Zabawa, ale bezużyteczny sposób". '+ 2' służy do utworzenia wyniku, o który OP prosi o – Automatico

71

W Ruby 1.9.3 jest chainable metoda zwana with_index które mogą być przykuty do map.

Na przykład: array.map.with_index { |item, index| ... }

6

Zawsze podobało mi składnię tego stylu:

a = [1, 2, 3, 4] 
a.each_with_index.map { |el, index| el + index } 
# => [1, 3, 5, 7] 

Wywoływanie each_with_index dostaje moduł wyliczający można łatwo mapę nad z indeksu dostępne.

+2

, w jaki sposób jest to inna forma [odpowiedź, udzielona prawie 5 lat przed twoją] (http://stackoverflow.com/a/4697573/1772830)? –