Skip to content Skip to sidebar Skip to footer

Add New Summary Row For Cols Share The Same Vales Of 2 Different Cols

I have a matrix algorithm: Input: const input = [ ['Camry', 'Toyota', 'Jan', 'Nowhere Town', '50'], ['Camry', 'Toyota', 'Feb', 'Nowhere Town', '70'], ['Camry', 'Toyota'

Solution 1:

You could use a combined key and a destructed array.

var array = [['Camry', 'Toyota', 'Jan', 'Nowhere Town', '50'], ['Camry', 'Toyota', 'Feb', 'Nowhere Town', '70'], ['Camry', 'Toyota', 'Jan', 'Random City', '3000'], ['Prius', 'Toyota', 'Jan', 'Nowhere Town', '60'], ['Prius', 'Toyota', 'Jan', 'Random Town', '60'], ['Prius', 'Toyota', 'Mar', 'Nowhere Town', '50'], ['Civic', 'Honda', 'Jan', 'Nowhere Town', '10'], ['Civic', 'Honda', 'Feb', 'Nowhere Town', '10'], ['Civic', 'Honda', 'Mar', 'Random Town', '10'], ['Civic', 'Honda', 'Mar', 'Random Town', '20']],
    result = [].concat(...array
        .reduce((m, [brand, make, month, town, amount]) => {
            var key = [brand, make, month].join('|'),
                data = m.get(key) || [['S', brand, make, month, '0']];

            data.push(['D', data.length, brand, town, amount]);
            data[0][4] = (+data[0][4] + +amount).toString();
            return m.set(key, data);
        }, newMap)
        .values()
    );

console.log(result.map(a => a.join(' ')));
.as-console-wrapper { max-height: 100%!important; top: 0; }

Solution 2:

You can use reduce to create object by brand, make and month and then use spread syntax and Object.values to get array of arrays.

const input = [['Camry', 'Toyota', 'Jan', 'Nowhere Town', '50'],['Camry', 'Toyota', 'Feb', 'Nowhere Town', '70'],['Camry', 'Toyota', 'Jan', 'Random City', '3000'],['Prius', 'Toyota', 'Jan', 'Nowhere Town', '60'],['Prius', 'Toyota', 'Jan', 'Random Town', '60'],['Prius', 'Toyota', 'Mar', 'Nowhere Town', '50'],['Civic', 'Honda', 'Jan', 'Nowhere Town', '10'],['Civic', 'Honda', 'Feb', 'Nowhere Town', '10'],['Civic', 'Honda', 'Mar', 'Random Town', '10'],['Civic', 'Honda', 'Mar', 'Random Town', '20'],]

const obj = input.reduce((r, [brand, make, month, city, value]) => {
  let key = `${brand}|${make}|${month}`;
  if(!r[key]) r[key] = [
    ['S', brand,  make, month, +value],
    ["D", 1, make, city, value]
  ]
  else {
    r[key][0][4] += +value;
    let prev = r[key].slice(-1)[0]
    r[key].push(["D",  prev[1] + 1, make, city, value]);
  }
  return r;
}, {})

const result = [].concat(...Object.values(obj))

console.log(result)

Solution 3:

The following breaks does the input in two steps. It heavily utilizes es6 features Map and the spread operator.

The first step converts the items into groups by generating a key value pair and then adding each item to a Map of arrays of items keyed by the generated key.

The second step takes the values from each group to create a header, and them creates a new array with the header as the first item. The groups are then combined into a single array.

const input = [['Camry', 'Toyota', 'Jan', 'Nowhere Town', '50'], ['Camry', 'Toyota', 'Feb', 'Nowhere Town', '70'], ['Camry', 'Toyota', 'Jan', 'Random City', '3000'], ['Prius', 'Toyota', 'Jan', 'Nowhere Town', '60'], ['Prius', 'Toyota', 'Jan', 'Random Town', '60'],    ['Prius', 'Toyota', 'Mar', 'Nowhere Town', '50'],    ['Civic', 'Honda', 'Jan', 'Nowhere Town', '10'], ['Civic', 'Honda', 'Feb', 'Nowhere Town', '10'], ['Civic', 'Honda', 'Mar', 'Random Town', '10'], ['Civic', 'Honda', 'Mar', 'Random Town', '20']]

const group = newMap();
input.map(x => [ x.slice(0,3).join('::'), ['D', ...x.slice(0,4), +x[4]] ])
  .forEach(([key, val]) => (group.get(key) || group.set(key, []).get(key)).push(val));

const result = [].concat(... Array.from(group.values())
  .map(x => [['S', ...x[0].slice(1,4), x.reduce((a, c) => a + c[5], 0)], 
  	...x.map(y => [...y.slice(0, 3), ... y.slice(4,6)])]));

console.log(result.map(x => x.toString()));

Post a Comment for "Add New Summary Row For Cols Share The Same Vales Of 2 Different Cols"