2011-03-26 51 views
4
array = [1,2,3,{:name => "Peter"}, "hello"] 
array.each do |element| # it can be "inject", "map" or other iterators 
    # How to return object "array" and position of "element" 
    # also next and priviouse "element" 
end 

當然我可以通過array.index[element]返回索引,但我在尋找更自然的解決方案。就像Rails的協會proxy_owner迭代時返回迭代對象和索引

的Ruby 1.8.7

我要輸出什麼?我想返回對象,我迭代(在我的情況下數組),迭代次數(each_with_index的情況下索引)和迭代的priviouse元素。

作爲輸入我有一個陣列和迭代器(每個,地圖,注入等)

+1

不'each_with_index'工作?如果是這樣,你可以做'array [i-1]','array [i + 1]'。 – sawa 2011-03-26 19:58:37

+0

'inject_with_index'或'select_with_index'怎麼辦? :)我認爲那裏提出了共同的方法 – fl00r 2011-03-26 20:00:47

+0

什麼是期望的輸出?顯示實際的輸入/輸出比試圖用文字解釋更好。 – tokland 2011-03-26 22:02:35

回答

6

使用Enumerable#each_cons。以下是ruby1.8.7 rdoc的副本。它應該在紅寶石1.8.7上工作。


  • each_cons(N){...}
  • each_cons(n)的

迭代連續元件的每個陣列的給定的塊。如果沒有給出塊,則返回一個枚舉器。


有了這個,你可以給一個數組:

['a', 'b', 'c', 'd', 'e'].each_cons(3).to_a 

# => ["a", "b", "c"], ["b", "c", "d"], ["c", "d", "e"]] 

或做:

['a', 'b', 'c', 'd', 'e'].each_cons(3) {|previous, current, nekst| 
    puts "#{previous} - #{current} - #{nekst}" 
} 

# => a - b - c 
# => b - c - d 
# => c - d - e 

如果你想指數之,

['a', 'b', 'c', 'd', 'e'].each_cons(3).to_a.each_with_index {|(previous, current, nekst), i| 
    puts "#{i + 1}. #{previous} - #{current} - #{nekst}" 
} 

# => 1. a - b - c 
# => 2. b - c - d 
# => 3. c - d - e 

可以傳遞數組相當普遍的其他普查員,例如,inject

['a', 'b', 'c', 'd', 'e'].each_cons(3).to_a.inject(''){|str, (previous, current, nekst)| 
    str << previous+current+nekst 
} 

# => "abcbcdcde" 
+0

非常聰明,熟練:)我會用它。但它實際上並不是我正在尋找的 – fl00r 2011-03-26 21:00:21

+1

你可以修復這個鏈接,並澄清它是否會給'a','b','c',然後''b','c','d' '或'a','b','c',然後是'd','e','f'? – 2011-03-26 22:03:23

+0

@Andrew感謝他們指出。我修好了它。 – sawa 2011-03-27 01:50:43

5

在ruby1.8的,有each_with_index

如果您希望在其他迭代器像injectmap,...,如果你正在使用ruby1.9,有Enumerator#with_index方法,你可以連接到不同的迭代器。

Enumerator#with_index

+0

所以沒有辦法知道這個對象是迭代的,什麼是priviouse和next值? – fl00r 2011-03-26 20:07:18

+0

你使用紅寶石1.9嗎?如果你使用'with_index',你可以同時獲得對象和索引。使用索引'i',你可以使用'array [i-1]'獲得前一個。你甚至想要更簡單的方法來訪問上一個/下一個元素? – sawa 2011-03-26 20:08:01

+0

對不起,沒有。稀土元素(1.8.7) – fl00r 2011-03-26 20:08:19

1

無法測試,但如果沒記錯的話:

a = [4, 3, 3, 1, 6, 6,1] 
p a.enum_for(:each_with_index).inject([]){ |m,args| m<<args } 
#=> [[4, 0], [3, 1], [3, 2], [1, 3], [6, 4], [6, 5], [1, 6]] 

替換選擇注入,拒絕或什麼的。隨着紅寶石1.9:

p a.each_with_index.inject([]){ |m,args| m<<args } 
+1

注意xs.inject([]){| m,args | m << args} = xs.map {| x | x} = xs.to_a。無論如何,在Ruby 1.9(可能是1.8.7),你應該能夠簡單地寫一個each_with_index.to_a – tokland 2011-05-20 17:41:06

1

編輯:這是1.9,我現在看到你的問題明確提到1.8.7。我會把它留在這裏作爲參考,但如果它打擾任何人,我可以刪除它。

澤已經指出Enumerator#with_index

http://www.ruby-doc.org/core/classes/Enumerator.html#M000303

例子:

>> [1,2,3].map.with_index { |x, i| [x,i] } 
=> [[1, 0], [2, 1], [3, 2]] 
>> [1,2,3].each_cons(2).with_index { |(x, y), i| p [x,y,i] } 
[1, 2, 0] 
[2, 3, 1] 
=> nil 

也與此相關的問題是Enumerator#nextEnumerator#peek,這將返回的下一個對象的枚舉,分別而無需向內移動內部位置。

http://www.ruby-doc.org/core/classes/Enumerator.html#M000307

http://www.ruby-doc.org/core/classes/Enumerator.html#M000308

+0

Rails 1.8.7?我相信它是1.9 – fl00r 2011-03-26 21:47:13

+0

是的,這是Ruby 1.9。 Rails 1.8.7是相當古老的順便說一句。 ;-) – 2011-03-26 21:48:13

+1

對於1.8.7,你可以用'.each_with_index.map'替換'.map.with_index'。 – 2011-03-26 22:05:28

3

Ruby的each_with_index功能可以很容易地重新創建:

ary = %w[zero one two three] 
ary.zip((0 .. (ary.size - 1)).to_a).to_a # => [["zero", 0], ["one", 1], ["two", 2], ["three", 3]] 

ary.zip((0 .. (ary.size - 1)).to_a).each do |a, i| 
    puts "this element: #{a}" 
    puts "previous element: #{ary[i - 1]}" if (i > 0) 
    puts "next element: #{ary[i + 1]}" if (i < (ary.size - 1)) 
    puts 
end 
# >> this element: zero 
# >> next element: one 
# >> 
# >> this element: one 
# >> previous element: zero 
# >> next element: two 
# >> 
# >> this element: two 
# >> previous element: one 
# >> next element: three 
# >> 
# >> this element: three 
# >> previous element: two 
# >> 

一旦你知道當前對象,你可以窺視到數組你遍歷指數輕鬆獲取上一個和下一個值。

所以,你可以這樣做:

module Enumerable 
    def my_each_with_index 
    self.zip((0 .. (self.size - 1)).to_a).each do |a, i| 
     yield a, i 
    end 
    end 
end 

ary.my_each_with_index { |a,i| puts "index: #{i} element: #{a}" } 
# >> index: 0 element: zero 
# >> index: 1 element: one 
# >> index: 2 element: two 
# >> index: 3 element: three 
+0

這是我發現的最有用的紅寶石智慧片段之一在StackOverflow問題的低排名答案中。 – 2016-03-31 18:17:41