Aryeh Beitz
Aryeh Beitz

Reputation: 2078

Extract non unique values from array

I can remove unique values from an array:

array_with_doubles = [[1, 2], [2, 3], [1, 2]]

using uniq:

array_with_doubles.uniq
# => [[1, 2], [2, 3]]

I want to find which values were removed.

Upvotes: 1

Views: 281

Answers (6)

iGian
iGian

Reputation: 11183

Another option, one liner:

array_with_doubles = [[1, 2], [2, 3], [1, 2], [1, 2], [3, 5], [3, 5]]

array_with_doubles.uniq.each_with_object(array_with_doubles) { |e, a| a.delete_at(a.rindex(e)) }
# => [[1, 2], [1, 2], [3, 5]]

Upvotes: 0

ray
ray

Reputation: 5552

I have solved above as below,

arr.inject([[],[]]) { |m, a| m[0].include?(a) ? m[1] << a : m[0] << a; m }[1]

Upvotes: 0

Ashik Salman
Ashik Salman

Reputation: 1879

You could try this:

 array_with_doubles.uniq.select { |x| array_with_doubles.count(x) > 1 }

Upvotes: 2

Amadan
Amadan

Reputation: 198324

You can get all removed elements like this:

array_with_doubles = [[1, 2], [2, 3], [1, 2], [1, 2]]
require 'set'
array_with_doubles.each_with_object(Set.new).inject([]) { |a, (e, seen)|
  a << e if seen === e
  seen << e
  a
}
# => [[1, 2], [1, 2]]

Unlike most other answers, if an element would be removed twice by uniq, both copies of it are shown by this code. uniq retains the first equal element, while this code rejects the first equal element.

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110675

The unique elements can be determined as follows:

arr = [1, 2, 3, 2, 1, 4, 1]

uniq = arr.each_with_object(Hash.new(0)) {|e,h| h[e] += 1}.select {|_,v| v == 1}.keys
  #=> [3, 4]

To remove the unique elements:

arr.reject { |e| uniq.include?(e) }
  #=> [1, 2, 2, 1, 1]

The nature of the objects in the array (numbers, arrays, hashes, instances, etc.) is not relevant to the question.

Determining the unique elements uses the form of Hash::new that takes an argument (here zero), which is the value returned by h[k] if the hash h does not have a key k. Therefore, the expression h[e] += 1, which Ruby expands to

h[e] = h[e] + 1

before evaluating it, becomes

h[e] = 0 + 1

if h does not have a key k. This is sometimes called a counting hash.

Upvotes: 0

Aryeh Beitz
Aryeh Beitz

Reputation: 2078

Given the array above

array_with_doubles = [[1,2], [2,3], [1,2]]

Simply run the following to get the array values appearing more than once

array_with_doubles.group_by{|x|x}.map_values(&:size).select {|k,v| v>1}.keys
# => [[1,2]]

Upvotes: 0

Related Questions