JS reduce - sum only array lengths in object

Viewed 202

I have the following data structure:

const arr = [    
    {key: 0, x: [], y: []},
    {key: 0, x: [], y: []}
]

I want to check if all arrays are empty, I have how can I do this using reduce? My code so far:

arr.reduce((count, acc) => {
    return acc !== 'key' ? count + acc.length : count
}, 0)
6 Answers

You could take key out of the object and check all length for having zero.

const
    array = [{ key: 0, x: [], y: [] }, { key: 0, x: [], y: [] }],
    allZero = array.every(({ key, ...o }) =>
        Object.values(o).every(({ length }) => !length));

console.log(allZero);

Summing

const
    array = [{ key: 0, x: [], y: [] }, { key: 0, x: [], y: [] }],
    sum = array.reduce((s, { key, ...o }) =>
        Object.values(o).reduce((t, { length }) => t + length, s), 0);

console.log(sum);

reduce is a bit of a clunky way to do this, and you're loopin over the items in the array, not the keys as (I think) you expected.

Use Array.every instead:

const arr = [    
    {key: 0, x: [], y: []},
    {key: 0, x: [], y: []}
]

const arr2 = [    
    {key: 0, x: [1,2,3], y: []},
    {key: 0, x: [], y: []}
]

function areAllEmpty(a){
    return a.every(i => i.x.length == 0 && i.y.length == 0); 
}

console.log(areAllEmpty(arr));
console.log(areAllEmpty(arr2));

Because acc will be the object in the array, you should check the object properties which are arrays. Use Object.values for this purpose, as well as another reduce for the arrays inside each object, and exclude key:

const arr = [    
    {key: 0, x: [], y: []},
    {key: 0, x: [], y: []}
];

const res = arr.reduce((a, { key, ...c }) => a + Object.values(c).reduce((e, { length: f }) => e + f, 0), 0);
console.log(res);

You can use filter() on Object.values to get only array values. And then flat() and add the length to result

const arr = [    
    {key: 0, x: [], y: []},
    {key: 0, x: [], y: []}
]

let res = arr.reduce((count, acc) => {
    return count + Object.values(acc).filter(x => x.constructor === Array).flat().length
}, 0)

console.log(res)

Sum only arrays' lengths in object using Array.reduce():

const arr = [    
    {key: 0, x: [], y: [], abc: "hsgg" },
    {key: 0, x: [1, 2, 3, 4], y: [1, 2]}
];

const c = arr.reduce((count, obj) => {
    Object.values(obj).forEach(v => {
      if(Array.isArray(v)) count += v.length;
    });
    return count;
}, 0);

console.log(c);

Note that in the other answers strings' lengths are also counted

Array.every is the better option. You can iterate over all the values of the objects and test to see if they're arrays and, if they are, return false if they're not empty. every will stop as soon as it finds a non-empty array, or end the of the iteration, whichever comes first.

const arr = [    
  {key: 0, x: [], y: []},
  {key: 0, x: [], y: []}
];

const arr2 = [    
  {key: 0, x: [], y: [1]},
  {key: 0, x: [], y: []}
];

const allEmpty = (arr) => arr.every(el => {
  for (let v of Object.values(el)) {
    if (Array.isArray(v) && v.length > 0) return false;
  }
  return true;
});

console.log(allEmpty(arr));
console.log(allEmpty(arr2));

Related