rb-
rb-

Reputation: 2365

Get items from Ruby Array that occur 2 or more times

Let's say I have a Ruby array.

[1,2,3,4,4,5,6,6,7,7]

I want to find the values that occur 2 or more times.

[4,6,7]

It will help my process to first determine which items occur only once then remove those. So I'd like to solve this by first finding the items that occur once.

Upvotes: 1

Views: 96

Answers (4)

Cary Swoveland
Cary Swoveland

Reputation: 110725

Another way:

a = [1,2,3,4,4,5,6,6,7,7]
au = a.uniq
a.reject { |i| au.delete(i) }
  #=> [4, 6, 7]

If efficiency is important, you could use a set:

require 'set'

s = Set.new
a.reject { |e| s.add?(e) }
  #=> [4, 6, 7]

Upvotes: 1

Paul.s
Paul.s

Reputation: 38728

Everyone loves a really difficult to follow one liner :)

[1,2,3,4,4,5,6,6,7,7].each_with_object(Hash.new(0)) { |o, h| h[o] += 1 }.select { |_, v| v > 1 }.keys

Add some white space and some comments

[1,2,3,4,4,5,6,6,7,7].each_with_object(Hash.new(0)) { |o, h| 
  h[o] += 1 
}.select { |_, v| 
  v > 1 
}.keys
  • Enumerate and pass in our memo hash to each iteration the Hash defaults to having 0 for any key
  • Increment counter for the object
  • Select only key value pairs where the value is greater than 1
  • Grab just the keys

This looks quite similar to Phillip's neat answer - in theory this should use slightly less memory as it will not have to build the intermediate arrays to perform counting

Upvotes: 3

ptierno
ptierno

Reputation: 10064

You can use Array#select to return the elements where Array#count is greater than 1:

2.1.2 :005 > arr = [1,2,3,4,4,5,6,6,7,7]
 => [1, 2, 3, 4, 4, 5, 6, 6, 7, 7]
2.1.2 :006 > arr.select { |e| arr.count(e) > 1 }.uniq
 => [4, 6, 7]

Hope this helps

Upvotes: 0

Philip Hallstrom
Philip Hallstrom

Reputation: 19889

There are probably better ways, but this is one:

> [1,2,3,4,4,5,6,6,7,7].group_by{|i| i}.reject{|k,v| v.size == 1}.keys
=> [4, 6, 7]

Breaking it down:

> a = [1,2,3,4,4,5,6,6,7,7]
=> [1, 2, 3, 4, 4, 5, 6, 6, 7, 7]
> a1 = a.group_by{|i| i}
=> {1=>[1], 2=>[2], 3=>[3], 4=>[4, 4], 5=>[5], 6=>[6, 6], 7=>[7, 7]}
> a2 = a1.reject{|k,v| v.size == 1}
=> {4=>[4, 4], 6=>[6, 6], 7=>[7, 7]}
> a2.keys
=> [4, 6, 7]

Upvotes: 5

Related Questions