2

I have this array structure in which at $arr[5]index I have a value that represents a number of occurrences for each object of my array $arr:

$arr=[
  [
    "some_value",
    "some_value",
    "cluster_0",
    "area_2",
    "some_value",
    "1"
  ],
  [
    "some_value",
    "some_value",
    "cluster_0",
    "area_2",
    "some_value",
    "2"
  ],
  [
    "some_value",
    "some_value",
    "cluster_0",
    "area_3",
    "some_value",
    "1"
  ],
  [
    "some_value",
    "some_value",
    "cluster_1",
    "area_3",
    "some_value",
    "3"
  ],
  [
    "some_value",
    "some_value",
    "cluster_1",
    "area_4",
    "some_value",
    "2"
  ],
  [
    "some_value",
    "some_value",
    "cluster_1",
    "area_4",
    "some_value",
    "2"
  ]
];

What I'm trying to obtain is to sum each of those$arr[5] values grouping by $arr[2](the cluster) and the $arr[3](the area).

Here's the expected output

$res=[
  [
    "cluster_0",
    "area_2",
    3
  ],
  [
    "cluster_0",
    "area_3",
    1
  ],
  [
    "cluster_1",
    "area_3",
    3
  ],
  [
    "cluster_1",
    "area_4",
    4
  ]
];

As you can see I have the sum of that specific value according to area and cluster matching. Is there any good approach in javascript for perform this kind of operation? I thought about a simple for loop and inside the loop an if condition for sum just the value that share the same $arr[2](the cluster) and the $arr[3](the area) values.

2 Answers 2

3

You could take the indices for the groups and the value index and generate a new result set with using the group as hash key. Then add the value to the group.

function groupBy(array, groups, value) {
    var result = [],
        hash = Object.create(null);

    array.forEach(function (a) {
        var keys = groups.map(function (i) { return a[i] }),
            key = keys.join('|');
        if (!hash[key]) {
            hash[key] = keys.concat(0);
            result.push(hash[key]);
        }
        hash[key][hash[key].length - 1] += +a[value];
    });
    return result;
}

var array = [["some_value", "some_value", "cluster_0", "area_2", "some_value", "1"], ["some_value", "some_value", "cluster_0", "area_2", "some_value", "2"], ["some_value", "some_value", "cluster_0", "area_3", "some_value", "1"], ["some_value", "some_value", "cluster_1", "area_3", "some_value", "3"], ["some_value", "some_value", "cluster_1", "area_4", "some_value", "2"], ["some_value", "some_value", "cluster_1", "area_4", "some_value", "2"]],
    result = groupBy(array, [2, 3], 5);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

Comments

1

Consider also this solution,

var data = $arr.reduce(function(acc, item) {
  var clusterName = item[2],
      areaName = item[3];
  acc[clusterName] = acc[clusterName] || {};
  acc[clusterName][areaName] = acc[clusterName][areaName] || 0;
  acc[clusterName][areaName] += parseInt(item[5]);
  return acc;
}, {});

console.log(data);

var array = Object.keys(data).reduce(function(acc, clusterItem) {
  Object.keys(data[clusterItem]).forEach(function(areaItem) {
    var item = [];
    item.push(clusterItem);
    item.push(areaItem);
    item.push(data[clusterItem][areaItem]);
    acc.push(item);
  });
  return acc;
}, []);

console.log(array);

Here at the first step all the items are calculated and added to the object. The second one converts the object to the required structure (array).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.