Forum: Ruby Returning a duplicate from an Array

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
78c53c84c7af015c7ae9f5c43322c2cc?d=identicon&s=25 Jeff Miller (ibanez270dx)
on 2009-01-13 23:01
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
03394cad6c346c9cccef6390e8f7cd89?d=identicon&s=25 Andy Cooper (Guest)
on 2009-01-13 23:06
(Received via mailing list)
> 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.
78c53c84c7af015c7ae9f5c43322c2cc?d=identicon&s=25 Jeff Miller (ibanez270dx)
on 2009-01-13 23:19
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
03394cad6c346c9cccef6390e8f7cd89?d=identicon&s=25 Andy Cooper (Guest)
on 2009-01-13 23:20
(Received via mailing list)
> > 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.
03394cad6c346c9cccef6390e8f7cd89?d=identicon&s=25 Andy Cooper (Guest)
on 2009-01-13 23:32
(Received via mailing list)
> 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
78c53c84c7af015c7ae9f5c43322c2cc?d=identicon&s=25 Jeff Miller (ibanez270dx)
on 2009-01-13 23:41
Thanks! That works great.

I appreciate the help!
 - Jeff Miller
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-01-14 10:48
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])
59193d8082ee0fe75675d3bb376cf2ba?d=identicon&s=25 Pierre Pierre (pierre_p)
on 2009-01-15 03:36
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 :-)
E7fe24cfaaf8af56ae28f63c81363172?d=identicon&s=25 Jimmy Kofler (koflerjim)
on 2009-01-15 12:19
> 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 :-)

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.
A745f7d401d0a9bf80a5d5d94c961a05?d=identicon&s=25 Tiago Nogueira (Guest)
on 2009-01-15 12:44
(Received via mailing list)
Jimmy Kofler escreveu:
> class Array
>
> 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
C88ad33f428f88c72f6aab47971564af?d=identicon&s=25 Klaus Stein (Guest)
on 2009-01-15 13:11
(Received via mailing list)
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 :-)
>
If order is not important:
h = Hash.new(0)
a.each { |x| h[x]+=1 }
h.select {|k,v| v>1 }.keys

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

Klaus
--
http://lapiz.istik.de/

The Answer is 42. And I am the Answer. Now I am looking for the
Question.
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 Jesús Gabriel y Galán (Guest)
on 2009-01-15 13:24
(Received via mailing list)
On Thu, Jan 15, 2009 at 12:18 PM, Jimmy Kofler
<koflerjim@mailinator.com> wrote:
>
> 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[x] += 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.
This topic is locked and can not be replied to.