2012-03-01 81 views
7

更新:對不起,我固定我的程序:如何比較`each`迭代器中的前一項?

a = [ 'str1' , 'str2', 'str2', 'str3' ] 
name = '' 
a.each_with_index do |x, i | 
    if x == name 
    puts "#{x} found duplicate." 
    else 
    puts x 
    name = x if i!= 0 
    end 
end 



    output: 
str1 
str2 
str2 found duplicate. 
str3 

是否有ruby語言的另一個美麗的方式做同樣的事情?

btw,實際上。在我的真實情況下,aActiveRecord::Relation

謝謝。

+1

嘗試用詞語解釋意圖,代碼看起來有問題(尤其是'x [i-1]'沒有意義)。最好的方法是:給出一些輸入和預期輸出的例子。 – tokland 2012-03-01 13:39:17

+0

謝謝,我修復了我的程序。 – 2012-03-01 14:14:13

+0

each_cons仍然適合嗎? – 2012-03-01 14:14:30

回答

16

你可能有each_cons的問題是,它迭代通過n-1對(如果Enumerable的長度是n)。在某些情況下,這意味着您必須單獨處理第一個(或最後一個)元素的邊界情況。

在這種情況下,它可以很容易的實現method類似each_cons,但會產生(nil, elem0)的第一個元素(相對於each_cons,這將產生(elem0, elem1)

module Enumerable 
    def each_with_previous 
    self.inject(nil){|prev, curr| yield prev, curr; curr} 
    self 
    end 
end 
12

您可以使用each_cons

irb(main):014:0> [1,2,3,4,5].each_cons(2) {|a,b| p "#{a} = #{b}"} 
"1 = 2" 
"2 = 3" 
"3 = 4" 
"4 = 5" 
3

您可以使用Enumerable#each_cons

a = [ 'str1' , 'str2', 'str3' , ..... ] 
name = '' 
a.each_cons(2) do |x, y| 
    if y == name 
    puts 'got you! ' 
    else 
    name = x 
    end 
end 
5

您可以使用each_cons

a.each_cons(2) do |first,last| 
    if last == name 
    puts 'got you!' 
    else 
    name = first 
    end 
end 
1

正如你可能想與重複的做多puts,我寧願保持在重複的結構:

### question's example: 
a = [ 'str1' , 'str2', 'str2', 'str3' ] 
# => ["str1", "str2", "str2", "str3"] 
a.each_cons(2).select{|a, b| a == b }.map{|m| m.first} 
# => ["str2"] 
### a more complex example: 
d = [1, 2, 3, 3, 4, 5, 4, 6, 6] 
# => [1, 2, 3, 3, 4, 5, 4, 6, 6] 
d.each_cons(2).select{|a, b| a == b }.map{|m| m.first} 
# => [3, 6] 

更多關於在:https://www.ruby-forum.com/topic/192355(David A. Black的很酷答案)