DEV Community

Discussion on: 5 Programming Patterns I Like

Collapse
 
idanarye profile image
Idan Arye

3. One loop two arrays

Is reduce really necessary here? Wouldn't it be so much clearer to do this with a forEach?

const exampleValues = [2, 15, 8, 23, 1, 32];
const truthyValues = [];
const falseyValues = [];
exampleValues.forEach(exampleValue => {
        if (exampleValue > 10) {
            truthyValues.push(exampleValue);
        } else {
            falseyValues.push(exampleValue);
        }
});

5. Nested ternaries

The same flow you used in the ternaries can be applied to the if statements:

let result = null;
if (!conditionA) {
    result = "Not A";
} else if (conditionB) {
    result = "A & B";
} else {
    result = "A";
}

And if you used the same flow as in your if statements but with ternaries, they'd also look weird:

const result = conditionA
    : (
        conditionB
        : "A & B"
        ? "A"
    )
    ? "Not A";

Also, I find ternaries formatting to be more readable this way:

const result =
    !conditionA ? "Not A"
    : conditionB ? "A & B"
    : "A";
Collapse
 
zegio profile image
Tony

HA! I posted the almost the exact same else-if logic before realizing you had!

Collapse
 
adamgerthel profile image
Adam Gerthel

I think reduce is nicer because it's always clear that an Array.reduce constructs "something" from an array. The whole statement includes everything you need to know (i.e. the final argument is the base value) as opposed to declaring the arrays before the loop. No need to look outside the reduce for answers since it's all there.

Reduce can be a little intimidating in the beginning but once you get the hang of it it's wonderful and makes a lot of sense.

Collapse
 
idanarye profile image
Idan Arye

So it's better because you can put it in a single statement, even though you now have to address the arrays as array[0] and array[1] instead of by name?

Thread Thread
 
adamgerthel profile image
Adam Gerthel

You don't! You could actually do this instead:

const [truthyValues, falseyValues] = exampleValues.reduce(([truthyValues, falseyValues], exampleValue) => {
  if (exampleValue > 10) {
    return [[...truthyValues, exampleValue], falseyValues];
  }

   return [truthyValues, [...falseyValues, exampleValue]];
}, [[], []]);

I've spread the array in the return statement because I wasn't too fond of the push along with having to return the two arrays.

Another one, using an object instead of two arrays would be:

const { truthyValues, falseyValues } = exampleValues.reduce((result, exampleValue) => {
  if (exampleValue > 10) {
    result.truthyValues.push(exampleValue)
  } else {
    result.falseyValues.push(exampleValue)
  }

   return result
}, { truthyValues: [], falseyValues: []});

Which in my opinion is probably the easiest one to read.

Thread Thread
 
idanarye profile image
Idan Arye

I've spread the array in the return statement because I wasn't too fond of the push along with having to return the two arrays.

Which is how reduce is meant to be used, and why it is needed in functional languages that deal with immutable data. Otherwise you are just abusing it as a loop construct to feel functional.

But I wouldn't recommend this style in Javascript, because arrays are not linked lists and this becomes O(n2).

Thread Thread
 
adamgerthel profile image
Adam Gerthel • Edited

I don't have a computer science background so what you're referring to is not something I can easily relate to. I have a vague idea of the concept of linked lists, but I don't understand the big O notation (entirely new concept to me).

Do you mean that it's less performant than needed? Because I'm creating a new array which contains two arrays both of which will have to be looped due to using the spread operator as opposed to a push (which would not need to loop the whole array)?

Sorry if I'm not very clear, I'm simply not very good with these concepts and I'm genuinely interested in understanding what you're saying.

Update: Ok, I think I understand now.. You're saying that my solution with the spread operator will decrease in performance for each value in the exampleValues array, which is a bad practice. And it's O(n2) (opposed to O(n)) because I'm doing it twice?

Thread Thread
 
idanarye profile image
Idan Arye

O(n2), not O(n2). As in - O(n*n). As the array get bigger, the spread operator takes more and more time to perform because it needs to copy more values, as opposed to push which only needs to add one value (and sometimes increase the size, which takes longer - but it doesn't do it on each push)

Thread Thread
 
adamgerthel profile image
Adam Gerthel

O(n2), not O(n2). As in - O(n*n)

I'm aware, I just don't know how to do it on my keyboard. And yes, I do realise there's a major difference and it shouldn't be trivialised..

Anyway, thanks - I learned something new today :)

Thread Thread
 
idanarye profile image
Idan Arye

dev.to does it for you with the ^ operator - so O(n^2) becomes O(n2).