7

update: sorry, I fixed my program:

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

Is there another beautiful way in ruby language to do the same thing ?

btw, actually. a is a ActiveRecord::Relation in my real case.

Thanks.

hey mike
  • 2,431
  • 6
  • 24
  • 29
  • 1
    try to explain with words the intent, the code seems buggy (particularly that `x[i-1]` makes no sense). The best way: give some examples of input and expected output. – tokland Mar 01 '12 at 13:39
  • Did each_cons still suitable? – hey mike Mar 01 '12 at 14:14

5 Answers5

22

The problem you might have with each_cons is that it iterates through n-1 pairs (if the length of the Enumerable is n). In some cases this means you have to separately handle edge cases for the first (or last) element.

In that case, it's really easy to implement a method similar to each_cons, but which would yield (nil, elem0) for the first element (as opposed to each_cons, which yields (elem0, elem1):

module Enumerable
  def each_with_previous
    self.inject(nil){|prev, curr| yield prev, curr; curr}
    self
  end
end
Mladen Jablanović
  • 43,461
  • 10
  • 90
  • 113
15

you can use 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"
Vasiliy Ermolovich
  • 24,459
  • 5
  • 79
  • 77
6

You can use each_cons

a.each_cons(2) do |first,last|
  if last == name
    puts 'got you!'
  else
    name = first
  end
end
megas
  • 21,401
  • 12
  • 79
  • 130
3

You may use 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
ZelluX
  • 69,107
  • 19
  • 71
  • 104
1

As you probably want to do more than puts with the duplicates, I would rather keep the duplicates in a structure:

 ### 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] 

More on at: https://www.ruby-forum.com/topic/192355 (cool answer of David A. Black)

ribamar
  • 1,435
  • 1
  • 16
  • 26