Mike K
Mike K

Reputation: 6501

How to return conditional arrays from an array of objects?

I'm wondering if it's possible to achieve the below in a cleaner/more efficient way?

const data = [
    { active: false },
    { active: false },
    { active: true },
    { active: false },
    { active: true },
]

const split = (data) => {
    const activeData = data.filter(({active}) => active).map(element => 1)
    const inactiveData = data.filter(({active}) => !active).map(element => 0)

    return [
        activeData,
        inactiveData,
    ]
}

console.log(split(data))

The problem here, I think, is that this approach is not efficient, because it's filtering and mapping through the same array twice. Is there a way to do it just once?

Upvotes: 0

Views: 707

Answers (3)

Get Off My Lawn
Get Off My Lawn

Reputation: 36341

You pretty much have a clean way to do it, however using multiple array functions requires more loops over the data.

Reduce will allow us to do this just once.

const data = [
    { active: false },
    { active: false },
    { active: true },
    { active: false },
    { active: true },
]

const split = (data) =>
  data.reduce((acc, {active}) => acc[+!active].push(+active) && acc, [[],[]])

console.log(split(data))

Upvotes: 0

Pointy
Pointy

Reputation: 413826

Unless your array is immense, it's not going to make any difference. However you could indeed do this in one pass through the array:

    const split = (data) =>
      data.reduce((rv, entry) => 
        (rv[+!entry.active].push(+entry.active), rv)
      , [[], []]);
      
    console.log(split([{active: true}, {active: false}, {active: false}]))

The + operators convert the boolean values to numbers (0 or 1). The "rv" parameter to the .reduce() callback is the "return value", or the accumulator into which the .reduce() callback builds up the result. In this code, the callback uses the "active" flag (negated) to pick either the first array (index 0) or the second array (index 1) in the accumulator "array of arrays". The value pushed into the chosen array is then either 0 or 1, again obtained from the "active" value by converting it to a number.

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386680

You could take a single loop and reduce the array using an object as target.

const
    data = [{ active: false }, { active: false }, { active: true }, { active: false }, { active: true }],
    { true: activeData, false: inactiveData } = data.reduce((r, { active }) =>
        (r[active].push(+active), r),
        { true: [], false: [] }
    );

console.log(activeData);
console.log(inactiveData);

Upvotes: 0

Related Questions