How to concat sub array in typescript or javascript?

How to concat sub array in typescript or javascript? In may case I want concat all values with same name.

My array is

[
  {
    name: "AAA"
    values: [[1573054321, 0], [1573054560, 0]]
  }, {
    name: "BBB"
    values: [[1573054388, 0], [1573054596, 0]]
  }
], [
  {
    name: "AAA"
    values: [[1573054355, 0], [1573054542, 0]]
  }, {
    name: "BBB"
    values: [[1573054325, 0], [1573054545, 0]]
  }
]

I want this in my output:

[
  {
    name: "AAA"
    values: [[1573054321, 0], [1573054560, 0], [1573054355, 0], [1573054542, 0]]
  }, {
    name: "BBB"
    values: [[1573054388, 0], [1573054596, 0], [1573054325, 0], [1573054545, 0]]
  }
]

My typescript exemple with a simple concat (allMetricSeries is my input):

let metricSeries: MetricSeries[] = [];
allMetricSeries.forEach(metrics => {
  metricSeries = metricSeries.concat(metrics);
});

5 answers

  • answered 2019-11-08 13:52 Rainer Plumer

    One way of doing it.

    resultObj = {};
    [[
      {
        name: "AAA",
        values: [[1573054321, 0], [1573054560, 0]]
      }, {
        name: "BBB",
        values: [[1573054388, 0], [1573054596, 0]]
      }
    ], [
      {
        name: "AAA",
        values: [[1573054355, 0], [1573054542, 0]]
      }, {
        name: "BBB",
        values: [[1573054325, 0], [1573054545, 0]]
      }
    ]].forEach((subArray) => {
        subArray.forEach((arr) => {
            const name = arr.name;
            if (!resultObj[name]) {
                resultObj[name] = arr.values.slice();
            } else {
                resultObj[name].push(...arr.values);
            }
        });
    });
    finalResult = Object.keys(resultObj).map((key) => {
        return {name: key, values: resultObj[key]}
    });
    

  • answered 2019-11-08 13:55 Nicolas

    You can use a simple loop with a new array to accomplish this.

    let array = [
      [{
        name: "AAA",
        values: [[1573054321, 0], [1573054560, 0]]
      }, 
      {
        name: "BBB",
        values: [[1573054388, 0], [1573054596, 0]]
      }],
      [{
        name: "AAA",
        values: [[1573054355, 0], [1573054542, 0]]
      }, 
      {
        name: "BBB",
        values: [[1573054325, 0], [1573054545, 0]]
      }]
    ];
    
    let output = {};
    // we loop every array
    array.forEach((subArray) => {
      // we loop every array of array
      subArray.forEach((data) => {
      // if the key does not exists, we create it.
       if(!output.hasOwnProperty(data.name)) {
          output[data.name] = {
            name: data.name,
            values: []
          };
        }
        // push the value.
         output[data.name].values = output[data.name].values.concat(data.values);
      })
    });
    
    // we returns only the values of our object.
    console.log(Object.values(output));

  • answered 2019-11-08 14:05 Anis R.

    One way would be to first build a dictionary of the form name => values, and then building our target array from that dictionary (by generating an object of the form {name: values} from each entry in the dictionary)

    //your initial array
    var arr = [[
      {
        name: "AAA",
        values: [[1573054321, 0], [1573054560, 0]]
      }, {
        name: "BBB",
        values: [[1573054388, 0], [1573054596, 0]]
      }
    ], [
      {
        name: "AAA",
        values: [[1573054355, 0], [1573054542, 0]]
      }, {
        name: "BBB",
        values: [[1573054325, 0], [1573054545, 0]]
      }
    ]];
    
    //temporary dictionary to help us build the new array
    //of the form {'AAA' => [values], 'BBB' => [values]}
    var dict = {};
    
    for(var sub of arr) {
      for(var x of sub) {
        if(dict[x.name]) {
          dict[x.name] = dict[x.name].concat(x.values);
        }
        else {
          dict[x.name] = x.values;
        }
      }
    }
    
    //now building the new array from the dictionary:
    var new_arr = [];
    for (key in dict) {
      new_arr.push({name:key, values:dict[key]});
    }
    
    console.log(new_arr);

  • answered 2019-11-08 14:53 udalmik

    One more option using reduce function:

    const input = [[
      {
        name: "AAA",
        values: [[1573054321, 0], [1573054560, 0]]
      }, 
      {
        name: "BBB",
        values: [[1573054388, 1], [1573054596, 2]]
      }
    ],
    [
      {
        name: "AAA",
        values: [[1573054355, 0], [1573054542, 0]]
      }, 
      {
        name: "BBB",
        values: [[1573054325, 0], [1573054545, 0]]
      }
    ]]
    
    const iterableResult = input
      // flatten sub array elements into one array
      .reduce((all, row) => [...all, ...row], [])
      // merge using hash map for performance considerations
      .reduce((cache, el) => {
        if (cache.has(el.name)) {
          // merge
          el = {
            ...el,
            values: [...cache.get(el.name).values, ...el.values]
          }
        }
        cache.set(el.name, el);
        return cache;
      }, new Map())
      // return values of map
      .values()
    
    var arrayResult = [...iterableResult];
    

  • answered 2019-11-08 15:10 StepUp

    Another way through reduce method and spread operator:

    let data = [
        [
            {
                name: "AAA",
                values: [[1573054321, 0], [1573054560, 0]]
            }, {
                name: "BBB",
                values: [[1573054388, 0], [1573054596, 0]]
            }
        ],
        [
            {
                name: "AAA",
                values: [[1573054355, 0], [1573054542, 0]]
            }, {
                name: "BBB",
                values: [[1573054325, 0], [1573054545, 0]]
            }
        ]
    ];
    
    
    const result = data.reduce((a, c) => {
        let innerResult = c.reduce((ia, ic) => {
            ia[ic.name] = ia[ic.name] || {name: ic.name, values:[]};
            ia[ic.name].values.push(ic.values);
            return ia;
        }, {});
    
        for (const key in innerResult) {
            a[key] = a[key] || {values: []};
            a[key].values.push(...innerResult[key].values);
        }
        return a;
    }, {});    
    console.log(result);