как сравнить с предыдущим элементом в итераторе `each`? - PullRequest
7 голосов
/ 01 марта 2012

обновление : извините, я исправил свою программу:

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 другой прекрасный способ сделать то же самое?

кстати, на самом деле.a - это ActiveRecord::Relation в моем реальном случае.

Спасибо.

Ответы [ 5 ]

18 голосов
/ 01 марта 2012

Проблема, с которой вы можете столкнуться с each_cons, заключается в том, что она перебирает пары n-1 (если длина Enumerable равна n).В некоторых случаях это означает, что вам нужно отдельно обрабатывать крайние случаи для первого (или последнего) элемента.

В этом случае действительно легко реализовать метод , аналогичный 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
13 голосов
/ 01 марта 2012

вы можете использовать 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"
5 голосов
/ 01 марта 2012

Вы можете использовать each_cons

a.each_cons(2) do |first,last|
  if last == name
    puts 'got you!'
  else
    name = first
  end
end
3 голосов
/ 01 марта 2012

Вы можете использовать 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
1 голос
/ 13 июля 2016

Поскольку вы, вероятно, хотите сделать больше, чем 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 (крутой ответ Дэвида А. Блэка)

...