Search code examples
javascriptunderscore.jslodash

How we can merge multidimensional array with JavaScript or underscore or lodash


How we can merge and join key value this code(javascript or undescore or lodash).

Array Data:

[[
    {
      "Product": "Men's Cut and Sewn",
      "Monday": 13,
      "Tuesday": 1.29,
      "Thursday": 10,
      "Friday": 2,
      "Saturday": 2.1,
      "Sunday": 12
    },
    {
      "Product": "Men's Inner",
      "Monday": 10,
      "Tuesday": 1.29,
      "Wednesday ": 2.6,
      "Thursday": 4.9,
      "Friday": 2,
      "Saturday": 20,
      "Sunday": 12
    }
  ],
  [
    {
      "Product": "Men's Cut and Sewn",
      "Monday": 10,
      "Tuesday": 45,
      "Wednesday": 45,
      "Thursday": 23,
      "Friday": 2,
      "Saturday": 3,
      "Sunday": 2
    },
    {
      "Product": "Men's Inner",
      "Monday": 1,
      "Tuesday": 1,
      "Thursday": 34,
      "Friday": 5,
      "Saturday": 34,
      "Sunday": 34
    }
  ]]

Expectation Data:

[{
 {
      "Product": "Men's Cut and Sewn",
      "Monday": 23,
      "Tuesday": 2.58,
      "Wednesday": 45,
      "Thursday": 33,
      "Friday": 4,
      "Saturday": 5.1,
      "Sunday": 14
    },
    {
      "Product": "Men's Inner",
      "Monday": 11,
      "Tuesday": 2.29,
      "Wednesday ": 2.6,
      "Thursday": 38.9,
      "Friday": 7,
      "Saturday": 54,
      "Sunday": 46
    }
}] 

I tried with this javaScript code

var finalArr = [];
for (var i = 0; i < arr.length - 1; i++) {

  if (i < arr.length - 1 && finalArr.length > 0) {
    var arr1 = finalArr;
    var arr2 = arr[i]
  } else {
    var arr1 = arr[i];
    var arr2 = arr[i + 1];
  }

  for (let obj1 of arr1) {
    var sampleObj = {};

    for (let obj2 of arr2) {
      if (obj1.Product === obj2.Product) {
        sampleObj.Product = obj1.Product;
        for (let day in obj1) {
          if (day !== 'Product') {
            sampleObj[day] = parseInt(obj1[day] + obj2[day]);
          }
        }
      }
    }

    finalArr.push(sampleObj);
  }
}

It can be n number of array and some array need to add key also if its not found with same Product (One array doesn't have 'Monday' key but in second array have 'Monday' key with same product then need to join both monday value).

enter image description here

this.url = ['assets/sample-dataset.xlsx', 'assets/sheet2.xlsx'];

this.jsonData = XLSX.utils.sheet_to_json(worksheet, { raw: true });

Two sheet two array data.Not able to merge these multiple array in one array. jsonData given two array with above image. Need to merge in one array [[array1],[array2]]


Solution

  • You can use lodash to create a pipeline function with _.flow(). The function flattens the sub-arrays to a single array, groups the items by the Product, and then maps the groups object back to array, and merges each group to a single object:

    const { flow, flatten, partialRight: pr, groupBy, map, mergeWith, isNumber } = _ // replace with imports in your code
    
    const fn = flow(
      flatten, // convert to a single array,
      pr(groupBy, 'Product'), // convert to groups by with the product as key
      pr(map, group => mergeWith({}, ...group, (a, b) => _.isNumber(a) ? _.add(a, b) : undefined)) // combine the items of each group to a single item 
    )
    
    const arr = [[{Product:"Men's Cut and Sewn",Monday:13,Tuesday:1.29,Thursday:10,Friday:2,Saturday:2.1,Sunday:12},{Product:"Men's Inner",Monday:10,Tuesday:1.29,"Wednesday":2.6,Thursday:4.9,Friday:2,Saturday:20,Sunday:12}],[{Product:"Men's Cut and Sewn",Monday:10,Tuesday:45,Wednesday:45,Thursday:23,Friday:2,Saturday:3,Sunday:2},{Product:"Men's Inner",Monday:1,Tuesday:1,Thursday:34,Friday:5,Saturday:34,Sunday:34}]]
    
    const result = fn(arr)
    
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.14/lodash.js"></script>

    And a terser version using lodash/fp:

    const { flow, flatten, groupBy, map, mergeAllWith, isNumber } = _ // replace with imports in your code
    
    const fn = flow(
      flatten, // convert to a single array,
      groupBy('Product'), // convert to groups by with the product as key
      map(mergeAllWith((a, b) => _.isNumber(a) ? _.add(a, b) : undefined)) // combine the items of each group to a single item 
    )
    
    const arr = [[{Product:"Men's Cut and Sewn",Monday:13,Tuesday:1.29,Thursday:10,Friday:2,Saturday:2.1,Sunday:12},{Product:"Men's Inner",Monday:10,Tuesday:1.29,"Wednesday":2.6,Thursday:4.9,Friday:2,Saturday:20,Sunday:12}],[{Product:"Men's Cut and Sewn",Monday:10,Tuesday:45,Wednesday:45,Thursday:23,Friday:2,Saturday:3,Sunday:2},{Product:"Men's Inner",Monday:1,Tuesday:1,Thursday:34,Friday:5,Saturday:34,Sunday:34}]]
    
    const result = fn(arr)
    
    
    console.log(result)
    <script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>