2012-03-01 79 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的很酷答案)