Returning a duplicate from an Array


#1

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 M.

#2

Thanks,

  • Jeff M.

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

Andy C…


#3

Andy C. 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 C…

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 M.

#4

Thanks,

  • Jeff M.

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

Andy C…

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 C…


#5

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 M.

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 C.


#6

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


#7

Thanks! That works great.

I appreciate the help!

  • Jeff M.

#8

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:


#9

Pierre P. 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.


#10

Jimmy K. 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


#11

Pierre P. removed_email_address@domain.invalid 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:

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.


#12

On Thu, Jan 15, 2009 at 12:18 PM, Jimmy K.
removed_email_address@domain.invalid 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 C. 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.