8

If I have an array of Sets, what is the best method to combine these Sets into a single Set?

Say if I had this array:

const array = [new Set([1, 2, 3]), new Set([4, 5, 6]), new Set([7, 8, 9])]

How would I manipulate this array in order to produce a single Set with the same output as:

new Set([1,2,3,4,5,6,7,8,9])

This array has an arbitrary number of sets of arbitrary size.

5
  • Have you tried anything? Commented Feb 7, 2018 at 6:36
  • new Set([...array[0], ...array[1], ...array[2]])? Commented Feb 7, 2018 at 6:37
  • I tried using the spread operator new Set(...array), but it only expands the first Set. I tried using the spread operator within array.map, but kept running into issues. new Set(array.map(set => ...set)) gives me the error Uncaught SyntaxError: Unexpected token ... Commented Feb 7, 2018 at 6:37
  • 1
    @D.Wood Spread syntax works only within array literals. It's not an operator that produces a value. Commented Feb 7, 2018 at 6:49
  • @Bergi Ah, I understand now. Thank you! Commented Feb 7, 2018 at 6:51

2 Answers 2

7

You can also use reduce

new Set( array.reduce( ( a, c ) => a.concat( [...c] ), [] ) )

Demo

var array = [new Set([1, 2, 3]), new Set([4, 5, 6]), new Set([7, 8, 9])];
var output = new Set( array.reduce( ( a, c ) => a.concat( [...c] ), [] ) );
console.log( [...output] );

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

4 Comments

NOTE: doing [...c] will eliminate duplicate entries in an "c" array,
@A.T. It will happen anyways since the output is expected to go in a Set and it will eliminate all duplicate entries anyways.
@A.T. No, the duplicates are already eliminated because c is a Set. Spreading it does not make a difference.
[...output] is actually converting the Set into an array. You could iterate over the set keys() or values() but it's easier to convert it into to array an console output it
5

The simplest is the best:

let result = new Set;
for (const set of array)
    for (const element of set)
        result.add(element);

Alternatively, if you want to use the constructor, I'd go for an immediately invoked generator function to create an iterator:

const result = new Set(function* () {
    for (const set of array)
        yield* set;
}());

Of course you can also declare a reusable functional-minded generator function for this:

function* flatten(iterable) {
    for (const inner of iterable)
        for (const element of inner)
            yield element;
}
const result = new Set(flatten(array));

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.