6

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.

valtism
  • 132
  • 3
  • 14
  • Have you tried anything? – Rajesh Feb 07 '18 at 06:36
  • `new Set([...array[0], ...array[1], ...array[2]])`? – Bergi Feb 07 '18 at 06: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 ...` – valtism Feb 07 '18 at 06:37
  • 1
    @D.Wood Spread *syntax* works only within array literals. It's not an operator that produces a value. – Bergi Feb 07 '18 at 06:49
  • @Bergi Ah, I understand now. Thank you! – valtism Feb 07 '18 at 06:51

2 Answers2

6

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] );
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
  • NOTE: doing [...c] will eliminate duplicate entries in an "c" array, – A.T. Feb 07 '18 at 06:55
  • 2
    @A.T. It will happen anyways since the output is expected to go in a `Set` and it will eliminate all duplicate entries anyways. – gurvinder372 Feb 07 '18 at 06:56
  • 2
    @A.T. No, the duplicates are already eliminated because `c` is a `Set`. Spreading it does not make a difference. – Bergi Feb 07 '18 at 06:57
  • `[...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 – I.G. Pascual Nov 27 '20 at 16:31
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));
Bergi
  • 630,263
  • 148
  • 957
  • 1,375