как сравнить с предыдущим элементом в "каждом" итераторе?
обновление: извините, я исправил свою программу:
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 ответов
проблема может быть с each_cons
он проходит через n-1
пары (если длина перечисляемого равна 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
можно использовать 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"
можно использовать each_cons
a.each_cons(2) do |first,last|
if last == name
puts 'got you!'
else
name = first
end
end
вы можете использовать перечисли#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
Как вы, вероятно, хотите сделать больше, чем 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 (прохладный ответ Дэвида А. Черный)