Returning a duplicate from an Array

J

Jeff Miller

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
 
J

Jeff Miller

Andy said:
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
 
B

Brian Candler

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

Pierre Pat

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 :)
 
J

Jimmy Kofler

Pierre said:
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.
 
T

Tiago Nogueira

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

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
 
K

Klaus Stein

Pierre Pat said:
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
 
J

Jesús Gabriel y Galán

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,970
Members
47,527
Latest member
RoxanneTos

Latest Threads

Top