Dragonfly
Dragonfly

Reputation: 4361

How to get all unique elements in for an array of array but keep max count of duplicates

The question doesn't make much sense but not sure how to word it without an example. If someone can word it better, feel free to edit it.

Let's say I have an array of arrays such as this:

[ ['a', 'a', 'b', 'c'], [], ['d', 'a'], ['b', 'b', 'b', 'e'] ]

I would like the output to be:

 ['a', 'a', 'b', 'b', 'b', 'c', 'd', 'e']

Not sure if there is an easy way to do this in javascript/jquery/underscore. One way I could think of is to look through each of these arrays and count up the number of times each element shows up and keep track of the maximum amount of times it shows up. Then I can recreate it. But that seems pretty slow considering that my arrays can be very large.

Upvotes: 0

Views: 65

Answers (4)

Salman Arshad
Salman Arshad

Reputation: 272096

You need to:

  • Loop over each inner array and count the values
  • Store each value and its count (if higher than current count) in a counter variable
  • In the end, convert the value and counts into an array

Following code shows a rough outline of the process. Remember to replace .forEach and for..in with appropriate code:

var input = [['a', 'a', 'b', 'c'], [], ['d', 'a'], ['b', 'b', 'b', 'e']],
    inputCount = {};
input.forEach(function(inner) {
    var innerCount = {};
    inner.forEach(function(value) {
        innerCount[value] = innerCount[value] ? innerCount[value] + 1 : 1;
    });
    var value;
    for (value in innerCount) {
        inputCount[value] = inputCount[value] ? Math.max(inputCount[value], innerCount[value]) : innerCount[value];
    }
});
console.log(inputCount);
// Object {a: 2, b: 3, c: 1, d: 1, e: 1} 

Upvotes: 1

Dragonfly
Dragonfly

Reputation: 4361

After messing around, I found a solution but not sure if I like it enough to use. I would probably use it if I can't think of another one.

I would use underscorejs countBy to get the count of all the elements.

var array = [ ['a', 'a', 'b', 'c'], [], ['d', 'a'], ['b', 'b', 'b', 'e'] ];

var count = _.map(array, function(inner) {
  return _.countBy(inner, function(element) {
    return element;
  });
});

var total = {};
_.each(_.uniq(_.flatten(array)), function(element) {
  var max = _.max(count, function(countedElement) {
    return countedElement[element];
  });

  total[element] = max[element];
});

console.log(total); // {a: 2, b: 3, c: 1, d: 1, e: 1} 

Then I would recreate the array with that total.

Upvotes: 1

Razvan
Razvan

Reputation: 3142

Not the most efficient solution but it should describe you the process:

var big = [ ['a', 'a', 'b', 'c'], [], ['d', 'a'], ['b', 'b', 'b', 'e'] ];

function map(arr){
    var map = {}
    for (var i=arr.length-1; i>-1; i--){
        if(arr[i] in map) map[arr[i]]++;
        else map[arr[i]] = 1;
    }
    return map;
}

function reduce(matrix){
    var arrMap = {};
    for (var i=matrix.length-1; i>-1; i--){
        var arrRes = map(matrix[i]);
        for (var key in arrRes){
            if( !arrMap[key] || arrMap[key] < arrRes[key])
                arrMap[key] = arrRes[key];
        }
    }
    return arrMap;
}

function calc(matrix){
    var res = [],
      arrMap = reduce(matrix);

    for (var key in arrMap){
        while(arrMap[key] > 0 ){
            res.push(key);
            arrMap[key]--;            
        }
    }
    return res;
}

console.log(calc(big));
// Array [ "e", "b", "b", "b", "a", "a", "d", "c" ]

Upvotes: 0

Mike Brant
Mike Brant

Reputation: 71384

Here is example of simple nested loop approach:

var input = [ ['a', 'a', 'b', 'c'], [], ['d', 'a'], ['b', 'b', 'b', 'e'] ];

var countMap = {};
// iterate outer array
for (i=0; i < input.length; i++) {
    // iterate inner array
    for (j=0; j < input[i].length; j++) {
        // increment map counter
        var value = input[i][j];
        if (countMap[input[i][j]] === undefined) {
            countMap[value] = 1;
        } else {
            countMap[value]++;
        }
    }
}
console.log(countMap); // output such as {'a':2, 'b':4, 'c':1, 'd':1, 'e':1}

Upvotes: 0

Related Questions