beeudoublez
beeudoublez

Reputation: 1242

Remove duplicates from nested array

I have an Array of Arrays that contains numbers in a particular order. I want to remove the duplicates out of the nested arrays, but there is a hierarchy: If a number occurs in a lower-index of the array, remove all duplicates down the Array chain.

Example: nums = [[10, 6, 14], [6], [10, 6, 9], [10, 13, 6], [10, 13, 6, 9, 16], [10, 13]]

nums[0] contains [10,6,14] so any subsequent mention of 10,6,14 should be removed from the other arrays in the chain, meaning nums[2] should have 10,6 removed and only 9 should remain.

I'm having trouble doing this with nested loops, can any Ruby wizards help please?

Upvotes: 3

Views: 1698

Answers (4)

tokland
tokland

Reputation: 67910

Yet another way. It keeps original order of elements in arrays:

require 'set'
nums = [[10, 6, 14], [6], [10, 6, 9], [10, 13, 6], [10, 13, 6, 9, 16], [10, 13]]
nums2 = nums.inject([[], Set.new]) do |(output, seen), ary|  
  [output << ary.reject { |a| seen.include?(a) }, seen.union(ary)]
end[0]
p nums2
# [[10, 6, 14], [], [9], [13], [16], []]

Upvotes: 1

Phrogz
Phrogz

Reputation: 303549

Is the following incorrect? Should the [6] be removed or not?

nums = [[10, 6, 14], [6], [10, 6, 9], [10, 13, 6], [10, 13, 6, 9, 16], [10, 13]]

def remove_duplicate_numbers( array )
  seen = []
  array.map{ |sub_array|
    result = sub_array - seen
    seen += sub_array
    result
  }
end

p remove_duplicate_numbers( nums )
#=> [[10, 6, 14], [], [9], [13], [16], []]

If this is not what you want, please post the actual output you expect for your array.

Upvotes: 0

MFreck
MFreck

Reputation: 196

require 'set'

nums = [[10, 6, 14], [6], [10, 6, 9], [10, 13, 6], [10, 13, 6, 9, 16], [10, 13]]
found = Set.new
new_nums = []

for subarray in nums do
    sub_new = []
    for i in subarray do
        if not found.member? i
            sub_new << i
        end
        found << i
    end
    new_nums << sub_new
end

puts(nums.inspect)
puts(new_nums.inspect)

Upvotes: 3

Theo
Theo

Reputation: 132972

This should do it:

input = [[10, 6, 14], [6], [10, 6, 9], [10, 13, 6], [10, 13, 6, 9, 16], [10, 13]]
seen = []
output = input.map do |numbers|
  new = numbers.uniq - seen
  seen += new
  new
end
# => output is [[10, 6, 14], [], [9], [13], [16], []]

If you want to remove the empty lists in the output, simply

output.reject!(&:empty?)

Upvotes: 10

Related Questions