Identify elements that are repeated within a two-dimensional array

2

In an array

a = [[1,"José"],[2,"Pedro"],[3,"Maria"],[4,"Lauro"],[2,"Pedro"],
     [5,"Léo"],[1,"José"],[6,"Caio"]]

How to get a new array b that shows the positions of the indexes with the arrays that repeat (equals) ?, in this case array b would look like this:

b = [[0,6],[1,4]]

I made a clone of the array comparing each position, but it was somewhat time consuming and also has the original positions that are included in array b making it the same array with the positions that are equal, / p>     

asked by anonymous 09.06.2014 / 11:28

2 answers

3

There are many ways to do this, but according to this benchmark , this is the most efficient solution: / p>

a = [[1,"José"],[2,"Pedro"],[3,"Maria"],[4,"Lauro"],[2,"Pedro"],
 [5,"Léo"],[1,"José"],[6,"Caio"]]

dups = {}
a.each_with_index do |val, idx|
    (dups[val] ||= []) << idx
end
dups.delete_if {|k,v| v.size == 1}

# => {[1, "José"]=>[0, 6], [2, "Pedro"]=>[1, 4]}
    
09.06.2014 / 16:15
1
a = [[1,"José"],[2,"Pedro"],[3,"Maria"],[4,"Lauro"],[2,"Pedro"],
     [5,"Léo"],[1,"José"],[6,"Caio"]]

By following the methods of the arrays we can set up the following:

each_index iterates over indexes. To know which indexes are equal to a given element we can do the following:

a.each_index.select{|i| a[i] == [1,"José"] }
# => [0, 6]

If you want to apply this to all elements of the array, first use uniq to generate a list with no reps and then map to transform each element into its indexes:

a.uniq.map{|el| a.each_index.select{|i| a[i] == el } }
# => [[0, 6], [1, 4], [2], [3], [5], [7]]

If you want to show only those that are some repetition, reject in the end everything that only exists once:

a.uniq.map{|el| a.each_index.select{|i| a[i] == el } }.reject{|is| is.size == 1 }
# => [[0, 6], [1, 4]]

Elegant, is not it?

    
09.06.2014 / 16:10