user3055938
user3055938

Reputation: 323

Count and log matching unknown data in an array

I need to look through an array of unknown values and count how many of each unique values there are and push the count and value into a new array. So let's say I have the following array:

["123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891"]

I want to take this array and get the following array out of it:

["123", 12, "456", 12, "678", 12, "891", 12]

This gets the value and the number of times it occurs no matter how many and what values are in the original array:

["value", number of occurences]

Here is my attempt at accomplishing this, that kinda worked, but it is very gross and I want to learn/use a cleaner method.

function _sortData(data) {
 var tempDataHolder = [];
 var dataId = data[0];
 var matches = 0;
 var dataLength = data.length;
 for (var i = 0; i <= dataLength - 1; i++) {
  if(dataId === data[i]) {
    matches++;
    data.splice(i, 1);
    i--;
  } else if(data.length === 1 && dataId === data[0]) {
    matches++;
  }
  if(i >= data.length){
    tempDataHolder.push(dataId, matches);
    if(data[0]){
      i = 0;
      dataLength = data.length;
      dataId = data[0];
      matches = 0;
    }
  }
 }
 return tempDataHolder;
}

EDIT: Man there are some awesome answers here. What would you guys say is the "best" solution? Either way I'm learning a lot from all the answers and they seem to all solve my issue.

Upvotes: 0

Views: 86

Answers (5)

Samuel Davidson
Samuel Davidson

Reputation: 791

I would save the occurrences into a count object. This takes advantage of the fact that every object in JS is basically a HashMap.

var inputArr = ["123", "456", "67","123", "456"... ];

var counter = {};
var outArr = [];
inputArr.foreach(function(number) {
  if(counter[number])
    counter[number] = counter[number] + 1;
  else
    counter[number] = 1;
});

for (var prop in counter) {
  if(counter.hasOwnProperty(prop)) {
    outArr.push([prop], counter[prop]);
  }
}

return outArr;

The above contains a little pseudocode for inputArr that will need to be corrected but this should work just fine without multiple iterations of any objects or arrays.

Upvotes: 1

trincot
trincot

Reputation: 350477

Here is a solution using reduce and Object.keys:

function sortData(data) {
  var map = data.reduce(function (map, val) {
    map[val] = (map[val] || 0) + 1;
    return map;
  }, {});
  return Object.keys(map).reduce(function (result, key) {
    return result.concat([key, map[key]]);
  }, []);
}

// Test it:
var data = ["123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891"];
var result = sortData(data);
console.log(result);

Upvotes: 1

Mathieu Schaeffer
Mathieu Schaeffer

Reputation: 792

Here's a solution :

var hashMap = {}; 

var list = ["123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891"];

list.forEach(function(u){
   if (!hashMap.hasOwnProperty(u)){
      hashMap[u] = 1;
   }
   else {
      hashMap[u] += 1;
   }
})

// hashMap : {
//  "123" : 12,
//  "456" : 12,
//  "678" : 12,
//  "891" : 12
// }

And if you want an array of the unique values :

var uniqueList = Object.keys(hashMap);

//uniqueList : ["123", "456", "678", "891"];

Upvotes: 1

user2182349
user2182349

Reputation: 9782

This approach uses the values in the array as property names and the property value is the number of times it is in the array.

// Input array
var gazinta = ["123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678",
 "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891",
 "123", "456", "678", "891", "123", "456", "678", "891"];
var gazada;

gazada = countEmUp(gazinta);
console.log(gazada);

function countEmUp(gazinta) {
    // i is a counter
    // counted is an object where the value to be counted is the property name and the value is the count
    // flattened is a single-dimensional array with each value followed by its count
    var i, counted = {}, flattened = [];

    // Loop through the array
    for (i = 0; i < gazinta.length; i++) {
        // If this is a new element, meaning the property doesn't exist in the counted object
        if (typeof counted[gazinta[i]] === "undefined") {
            // Initialize it to zero
            counted[gazinta[i]] = 0;
        }
        // Increment the counter
        counted[gazinta[i]]++;
    }
    // Loop through the counted object and push the elements and counts onto the flattened array
    for (i in counted) {
        flattened.push(i,counted[i]);
    }
    return flattened;
}

Upvotes: 1

Neil DCruz
Neil DCruz

Reputation: 195

You can use a javascript object with the elements as keys and the count as values. Once you have looped through the original array you can loop through the hash map and convert to the array you desire.

JS

var a = ["123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891", "123", "456", "678", "891"];
var counter = {};
for ( var i = 0; i < a.length ; i ++) {
    var currentKey = a[i];
  if(counter.hasOwnProperty(currentKey)) {
    counter[currentKey] += 1;
  } else {
    counter[currentKey] = 1;
  }
}

Counter will be a hashmap of value <--> count pairs:

Object {123: 12, 456: 12, 678: 12, 891: 12}

You can loop through the object and convert it to the array desired:

var condensedArr = [];
for (var key in counter) {
    condensedArr.push(key);
  condensedArr.push(counter[key]);
}

Here is a working JSFiddle

Upvotes: 1

Related Questions