marcamillion
marcamillion

Reputation: 33755

How do I detect duplicate values within an array in Ruby?

Say I have an array that looks like:

a = [cat, dog, cat, mouse, rat, dog, cat]

How do I cycle through that, and do something with duplicates - e.g. say delete them?

In other words, if I did a.each do |i|, how do I evaluate a[0], against a[1], a[2], a[3]...and then when I find the one I want, say a[2] in this case has the first duplicate, I then push it to a stack or remove it or something.

I know how to evaluate keys, versus values...but how do I evaluate values against each other within the same array?

Thanks.

Upvotes: 9

Views: 14251

Answers (10)

Callan A. Carr
Callan A. Carr

Reputation: 11

The best way to do it is to compare it with a unique version of itself. If its the same then it has no duplicates, if not then duplicates exist.

unique_array = original_array.uniq

get a unique version of your array

if original_array == unique_array then return true else return false

compare it to your original array.

Simple!

Upvotes: 1

astgtciv
astgtciv

Reputation: 770

If array is sortable, then something like below will return only the duplicates.

array.sort.each_cons(2).select {|p| p[0] == p[1] }.map &:first

Sorts the array, then maps it to consecutive pairs of elements, selects pairs which are same, maps to elements.

Upvotes: 0

ingrid
ingrid

Reputation: 555

If you just want to get rid of duplicates, the easiest thing to do is take the array and do array&array. Use the & operator.

If you want to know what those repeats are, just compare array to array&array.

Upvotes: 0

jorgenj
jorgenj

Reputation: 31

This will print all the duplicates in an array:

array.inject(Hash.new(0)) { |hash,val| 
  hash[val] += 1; 
  hash 
}.each_pair { |val,count| 
  puts "#{val} -> #{count}" if count > 1 
}

Upvotes: 1

ch4nd4n
ch4nd4n

Reputation: 4197

You can create a hash to store number of times any element is repeated. Thus iterating over array just once.

h = Hash.new(0)
['a','b','b','c'].each{ |e| h[e] += 1 }

Should result

 {"a"=>1, "b"=>2, "c"=>1}

Upvotes: 13

spas
spas

Reputation: 1934

Try this:

array.inject({}){|h, e| h[e] = h[e].to_i + 1; h}

Upvotes: 3

Aleksander Pohl
Aleksander Pohl

Reputation: 1695

This works efficiently and is rather simple:

require 'set'

visited = Set.new
array.each do |element|
  if visited.include?(element)
    # duplicated item
  else
    # first appearance
    visited << element
  end
end

Upvotes: 6

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230326

A simple solution is to run a double loop:

a.each_with_index do |a1, idx1|
  a.each_with_index do |a2, idx2|
    next if idx1 >= idx2 # Don't compare element to itself 
                         # and don't repeat comparisons already made

    # do something with a pair of elements (a1, a2)
  end
end

If you just want to eliminate duplicates, there's a method: Array#uniq.

Upvotes: 1

MMM
MMM

Reputation: 7310

Try this:

class Array
    def find_dups
        uniq.map {|v| (self - [v]).size < (self.size - 1) ? v : nil}.compact
    end
end

a = ['cat', 'dog', 'cat', 'mouse', 'rat', 'dog', 'cat']

print a - a.find_dups # Removes duplicates

find_dups will return elements that have duplicates

Upvotes: 4

lesce
lesce

Reputation: 6324

Use a.uniq! to remove duplicates .

also checkout the ruby-doc.org where you can find more info on ruby's class methods .

Upvotes: 2

Related Questions