0

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?

8
  • do you want only ones and zeros? please add the wanted result. Commented Aug 4, 2020 at 14:02
  • 1
    Define data just with array: [false, false, true, false, true] Commented Aug 4, 2020 at 14:03
  • The result is not particularly important, it could be mapped to anything. I'm just asking if it's possible to avoid cycling through the same array twice, as in the example. The only requirement here, is that data is an array of objects. Commented Aug 4, 2020 at 14:04
  • Cleaner will most likely be Opinion-based... Commented Aug 4, 2020 at 14:05
  • 1
    instead of .map() you can use .fill(1) and .fill(0) Commented Aug 4, 2020 at 14:13

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

This an interesting approach and seems to be what I'm looking for. Can you please elaborate what's going on here? Does rv here refer to both of the initial arrays of the reducer? Also, it doesn't seem to work without the cast number (doing (rv[+!entry.active].push(+entry.active), rv) seems to crash it), does this mean it'll only work with numbers and not boolean values, for example?
@MikeK I'll add a little explanation to the answer; it's basically what .reduce() is all about.
0

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);

1 Comment

This only returns one array, is it possible to return two, as in the OP approach?
0

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))

2 Comments

Is acc here always both of the arrays? If so, how do you determine which one to push to, if you're always just pushing to the acc?
This is just another variation of what @Pointy did.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.