Returning a duplicate from an Array

Hey guys,
I have an array of names that may contain duplicates. What I would like
to do is return an array OF THE DUPLICATES. I was looking around at
various built-in methods for arrays, but the closest thing I can find is
Array.uniq, which returns the array without the duplicates.

Any suggestions on how to do this?

Thanks,
- Jeff Miller

···

--
Posted via http://www.ruby-forum.com/.

Hey guys,
I have an array of names that may contain duplicates. What I
would like
to do is return an array OF THE DUPLICATES. I was looking around at
various built-in methods for arrays, but the closest thing I
can find is
Array.uniq, which returns the array without the duplicates.

Any suggestions on how to do this?

Thanks,
- Jeff Miller
--

Without really looking into it a quick and dirty way would be to just
subtract the results of .uniq from the initial array.

Andy Cooper.

Andy Cooper wrote:

Without really looking into it a quick and dirty way would be to just
subtract the results of .uniq from the initial array.

Andy Cooper.

Thanks for the quick reply! However, after trying it, I found that
subtracting an array from an array will delete each instance of an
element, leaving me with a blank array, IE:

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]

Any other ideas?

Thanks again,
- Jeff Miller

···

--
Posted via http://www.ruby-forum.com/\.

> Hey guys,
> I have an array of names that may contain duplicates. What I
> would like
> to do is return an array OF THE DUPLICATES. I was looking around at
> various built-in methods for arrays, but the closest thing I
> can find is
> Array.uniq, which returns the array without the duplicates.
>
> Any suggestions on how to do this?
>
> Thanks,
> - Jeff Miller
> --

Without really looking into it a quick and dirty way would be to just
subtract the results of .uniq from the initial array.

Andy Cooper.

Nevermind that wont work afterall, wasn't thinking about how arrays work
at the time.

  def dups(ary=)
    uniq=ary.uniq
    ary.reject{|z| if(uniq.include?(z));q-=[z];true;end}
  end

There that should do the trick. Still very probably not the best of
ways to do it though.

Andy Cooper.

Andy Cooper wrote:
>
> Without really looking into it a quick and dirty way would
be to just
> subtract the results of .uniq from the initial array.
>
> Andy Cooper.

Thanks for the quick reply! However, after trying it, I found that
subtracting an array from an array will delete each instance of an
element, leaving me with a blank array, IE:

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]

Any other ideas?

Thanks again,
- Jeff Miller
--

Yeah, I am winning the typing contest today.

  def dups(ary=)
    uniq=ary.uniq
    ary.reject{|z| if(uniq.include?(z));q-=[z];true;end}
  end

Should actually be

   def dups(ary=)
     uniq=ary.uniq
     ary.reject{|z| if(uniq.include?(z));uniq-=[z];true;end}
   end

Made a mistake when I made q make more sense aparently.

Andy Cooper

This version does only a single pass through the array:

  def dups(ary)
    seen = {}
    ary.find_all { |x| seen[x] || (seen[x]=true; false) }
  end

  p dups([1,2,3,1,4,5,6,3])

···

--
Posted via http://www.ruby-forum.com/.

Thanks! That works great.

I appreciate the help!
- Jeff Miller

···

--
Posted via http://www.ruby-forum.com/.

I'd do like this:
a.select{|x| a.index(x) != a.rindex(x)}.uniq

Now, I wouldn't know which one is more efficient, but coding wise, I
like that way :slight_smile:

···

--
Posted via http://www.ruby-forum.com/.

Pierre Pat wrote:
I'd do like this:
a.select{|x| a.index(x) != a.rindex(x)}.uniq

Now, I wouldn't know which one is more efficient, but coding wise, I
like that way :slight_smile:

Here's yet another take on it:

class Array
   def dups
      uniq.select{ |e| (self-[e]).size < self.size - 1 }
   end
end

p [ 1, 1, 2, 2, 3, 3, 4, 5 ].dups #=> [1, 2, 3]

see: http://snippets.dzone.com/posts/show/4148

Cheers,

j.k.

···

--
Posted via http://www.ruby-forum.com/\.

If order is not important:
h = Hash.new(0)
a.each { |x| h+=1 }
h.select {|k,v| v>1 }.keys

should be O(n) and with only one iteration through a.

Klaus

···

Pierre Pat <theyojimbo@gmail.com> wrote:

I'd do like this:
a.select{|x| a.index(x) != a.rindex(x)}.uniq

Now, I wouldn't know which one is more efficient, but coding wise, I
like that way :slight_smile:

--

The Answer is 42. And I am the Answer. Now I am looking for the Question.

Jimmy Kofler escreveu:

Pierre Pat wrote:
I'd do like this:
a.select{|x| a.index(x) != a.rindex(x)}.uniq

Now, I wouldn't know which one is more efficient, but coding wise, I like that way :slight_smile:
    
Here's yet another take on it:

class Array
   def dups
      uniq.select{ |e| (self-[e]).size < self.size - 1 }
   end
end

p [ 1, 1, 2, 2, 3, 3, 4, 5 ].dups #=> [1, 2, 3]

see: http://snippets.dzone.com/posts/show/4148

Cheers,

j.k.
  

I Think that the way :

class Array
   def dups
      uniq.select{ |e| (self-[e]).size < self.size - 1 }
   end
end
p [ 1, 1, 2, 2, 3, 3, 4, 5 ].dups #=> [1, 2, 3]

is more elegant!

tiago

class Array
  def dups
     uniq.select{ |e| (self-[e]).size < self.size - 1 }
  end
end

p [ 1, 1, 2, 2, 3, 3, 4, 5 ].dups #=> [1, 2, 3]

Regarding this and other solutions: the OP accepted a solution from
Andy Cooper which return *all* duplicates.
I mean, if a number appears three times, it will appear two in the
solution, and not one:

irb(main):001:0> a = [1,1,1,1,2,2,3,4,5,5,5]
=> [1, 1, 1, 1, 2, 2, 3, 4, 5, 5, 5]
irb(main):008:0> class Array
irb(main):009:1> def dups
irb(main):010:2> uniq.select{ |e| (self-[e]).size < self.size - 1 }
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> a.dups
=> [1, 2, 5]

Should be [1,1,1,2,3,4,5,5]. If order is not important:

irb(main):014:0> class Array
irb(main):015:1> def dups
irb(main):016:2> h = Hash.new 0
irb(main):017:2> each {|x| h += 1}
irb(main):018:2> h.inject() {|res, (k,v)| res << ([k] * (v-1)) if v

1; res.flatten}

irb(main):019:2> end
irb(main):020:1> end
=> nil
irb(main):021:0> a.dups
=> [5, 5, 1, 1, 1, 2]

Jesus.

···

On Thu, Jan 15, 2009 at 12:18 PM, Jimmy Kofler <koflerjim@mailinator.com> wrote: