0

I'm trying to do union of different arrays:

const info1 = {id: 1}
const info2 = {id: 2}
const info3 = {id: 3}

const array1 = [info1, info2]
const array2 = [info1, info3]
const array3 = [info2, info3]

const union = [...new Set([...array1, ...array2, ...array3])]

console.log(union)

It's possible in my code that some or all array1, array2, array3 can be null, this is not shown in the code above.

However when one or more of them are null I get the error for example if array1 was assigned to null: array1 is not iterable.

How can I prevent getting this error?

5
  • 2
    ...by not making them null? Or by checking if they're null before adding to the Set? Commented Jan 28, 2021 at 14:58
  • Do a null check before the union. Commented Jan 28, 2021 at 15:00
  • That is a bunch of null check that I would need to add? Commented Jan 28, 2021 at 15:02
  • 1
    Well, yeah, if you want arrays you can use arrays and have it easy, but if you also want null you need to deal with it somehow. Commented Jan 28, 2021 at 15:04
  • How come a null guard not a solution? Commented Jan 28, 2021 at 15:05

5 Answers 5

4

You can use the nullish coalescing operator to fall back to an empty array if the 'array' is actually null.

const union = [
  ...new Set([...(array1 ?? []), ...(array2 ?? []), ...(array3 ?? [])]),
];
Sign up to request clarification or add additional context in comments.

1 Comment

Please note that this operator isn't supported on every browser
2

You can create a function that will perform the extra null check for you.


const info1 = {
  id: 1
};

const info2 = {
  id: 2
};

const info3 = {
  id: 3
};

const array1 = [info1, info2];
const array2 = [info1, info3];
const array3 = [info2, info3];
const array4 = null;


// the spread operator here allow us to target every argument
// of the function
function union(...arrays) {
  // the filter removes the *nullish* values
  return Array.from(new Set(arrays.filter(x => !!x).flat()));
}

console.log(union(array1, array2, array3, array4))


/!\ Attention

One more thing, when you use a Set to remove the duplicates. It removes the duplicates because they are the same object. If you create a new object, containing the same id, it will not be detected as the same value, because you compare reference and not the underlying values.

const info1 = {
  id: 1
};

const info2 = {
  id: 2
};

const info3 = {
  id: 3
};

const array1 = [info1, info2];
const array2 = [info1, info3];

const array3 = [info2, {
  id: 3
}];

const array4 = null;


function union(...arrays) {
  return Array.from(new Set(arrays.filter(x => !!x).flat()));
}

console.log(union(array1, array2, array3, array4))

2 Comments

arrays.flat().filter(x => !!x)) -> shouldn't this be arrays.filter(x => !!x)).flat()? Seems valid to want to know of objects that are null but ignore arrays that are null.
@VLAZ yes true!
1

Modify your code as if an array gives you a null value then replace null with empty array to work properly as:

const info1 = {id: 1}
const info2 = {id: 2}
const info3 = {id: 3}

const array1 = [info1, info2]
const array2 = [info1, info3]
const array3 = null
const isNotNull=(array)=> array ? array : []

const union = [...new Set([...isNotNull(array1), ...isNotNull(array2), ...isNotNull(array3)])]

console.log(union)

function isNotNull checks an array if it equals null then it return an empty array

Comments

1

The most simple method is to use a Array#flatMap approach with a default array for virable with either an array or null.

unique = Array.from(new Set([array1, array2, array3].flatMap(v => v || [])));

Comments

0

Create a function that uses the rest operator to loop through each array;

Check if for null, otherwise, add to the set

const info1 = {id: 1}
const info2 = {id: 2}
const info3 = {id: 3}

const array1 = [info1, info2]
const array2 = [info1, info3]
const array3 = null;

function createSet(...all) {

    // Tmp hold
    let a = [];

    // For each given array
    for (var i = 0; i < all.length; i++) {

        // If it's not null, add
        if (all[i]) {
            a.push(...all[i]);
        }
    }

    // Create and return set
    return [...new Set(a)];
}


console.log(createSet(array1, array2, array3));

Comments

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.