Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge arrays matching a particular key value in JavaScript

Tags:

javascript

I have an array which is like this:

var arr = [{
  "date": "JAN",
  "value": 5,
  "weight": 3
}, {
  "date": "JAN",
  "value": 4,
  "weight": 23
}, {
  "date": "FEB",
  "value": 9,
  "weight": 1
}, {
  "date": "FEB",
  "value": 10,
  "weight": 30
}]

I want to match the primary key which is heredate. Matching this I want to merge the rest of the key values and get this following output:

[{
  "date": "JAN",
  "value": [5, 4],
  "weight": [3, 23]
}, {
  "date": "FEB",
  "value": [9, 10],
  "weight": [1, 30]
}]

I have written a function like this but can't figure out how to concat the key values:

var arr = [{
  "date": "JAN",
  "value": 5,
  "weight": 3
}, {
  "date": "JAN",
  "value": 4,
  "weight": 23
}, {
  "date": "FEB",
  "value": 9,
  "weight": 1
}, {
  "date": "FEB",
  "value": 10,
  "weight": 30
}]

const transform = (arr, primaryKey) => {
  var newValue = [];
  for (let i = 0; i < arr.length; i++) {
    for (let j = 1; j < arr.length; j++) {
      if (primaryKey[i] === primaryKey[j]) {
        newValue.push({
          ...arr[i],
          ...arr[j]
        });
      }
    }
  }
  return newValue
};

console.log(transform(arr,'date'))

2 Answers

  • Using Array#reduce, iterate over the list while updating a Map where the key is the primary-key and the value is the grouped object. In every iteration, create/update the pair.
  • Using Map#values, return the list of grouped objects

const transform = (arr, primaryKey) => [...
  arr.reduce((map, { [primaryKey]: key, ...e }) => {
    const { [primaryKey]: k, ...props } = map.get(key) ?? {};
    for(let prop in e) {
      props[prop] = [...(props[prop] ?? []), e[prop]];
    }
    map.set(key, { [primaryKey]: key, ...props });
    return map;
  }, new Map)
  .values()
];

const arr = [ { "date": "JAN", "value": 5, "weight": 3 }, { "date": "JAN", "value": 4, "weight": 23 }, { "date": "FEB", "value": 9, "weight": 1 }, { "date": "FEB", "value": 10, "weight": 30 } ]; 
console.log( transform(arr, 'date') );
like image 121
Majed Badawi Avatar answered Oct 29 '25 20:10

Majed Badawi


The following code should work:

const transform = (arr, primaryKey) => {
    var newValue = [];
    for(let i = 0; i < arr.length; i++){
        arr[i]["value"] = [arr[i]["value"]];
        arr[i]["weight"] = [arr[i]["weight"]];
    }
    newValue.push(arr[0])
    for(let i = 1; i < arr.length; i++){
        let contains = false;
        for(let j = 0; j < newValue.length; j++){
            if(newValue[j][primaryKey] == arr[i][primaryKey]){
                newValue[j]["value"].push(arr[i]["value"][0]);
                newValue[j]["weight"].push(arr[i]["weight"][0]);
                contains = true;
            }
        }
        if(!contains){
            newValue.push(arr[i]);
        }
        
    }
   return newValue
};

var arr = [{
              "date": "JAN",
              "value": 5,
              "weight": 3
          }, {
              "date": "JAN",
              "value": 4,
              "weight": 23
          }, {
              "date": "FEB",
              "value": 9,
              "weight": 1
          }, {
              "date": "FEB",
              "value": 10,
              "weight": 30
          }] 
          
var newthing = transform(arr,"date");
console.log(newthing);

Output:

[ { date: 'JAN', value: [ 5, 4 ], weight: [ 3, 23 ] },
  { date: 'FEB', value: [ 9, 10 ], weight: [ 1, 30 ] } ]

The way this code works is that first, we turn the values of the keys for "value" and "weight" into lists.

Then, we begin by pushing the first element of arr into newValue.

From here, we do a nested for loop to iterate through the remaining of arr and newValue:

If the value of "date" for every element of arr already exists in newValue, then we will push in the values of "value" and "weight" that belongs to arr.

However, if it does not exist, then we will simply push that element inside of newValue.

I hope this helped answer your question! Pleas let me know if you need any further help or clarification :)

like image 25
Aniketh Malyala Avatar answered Oct 29 '25 19:10

Aniketh Malyala