norbitrial
norbitrial

Reputation: 15166

Using reduce without return keyword by looking for unique values in an array

I like to use Array.prototype.reduce() for several different scenarios in my code, it's pretty straightforward and handy.

Please observe in the 2 different solutions below the reduce() function takes 2 different initial values, in the first case is new Set() and the second is [].

In the below example the code uses reduce() without return keyword - Set one:

const data = ['a', 'b', 'c', 'd', 'a', 'k', 'b'];
const result = data.reduce((a, c) => a.add(c), new Set());
console.log(Array.from(result));

The next example is using still reduce() but here with a return keyword - Array one:

const data = ['a', 'b', 'c', 'd', 'a', 'k', 'b'];
const result = data.reduce((a, c) => {
  a.find(e => e === c) ? null : a.push(c);
  return a;
}, []);
console.log(result);

Question:

So the .add() function for Set returns the Set object itself. The .push() function for Array returns the length of the used Array.

The Set case helps me to shorten the code using .reduce() without return keyword because the above mentioned reason. In my second example I would like to use the solution without return keyword but still with Array somehow.

Is there any workaround solution to get the same result but without using return keyword in the second example? I would like to shorten the code further if possible.

Any help is appreciated.

Upvotes: 1

Views: 947

Answers (2)

VLAZ
VLAZ

Reputation: 28994

Array#concat can add a new item to an array and returns a new array, so can works similar to Set#add. However, it still needs the conditional operator since you want to either add an element or nothing - for the latter case that's concatenating an array with an empty array:

const data = ['a', 'b', 'c', 'd', 'a', 'k', 'b'];
const result = data.reduce((a, c) => a.concat(a.some(e => e === c) ? [] : c), []);
console.log(result);

Alternatively, you can use spread syntax to again combine two arrays:

const data = ['a', 'b', 'c', 'd', 'a', 'k', 'b'];
const result = data.reduce((a, c) => [...a, ...(a.some(e => e === c) ? [] : c)], []);
console.log(result);

Neither of the two is perfect, to be honest. The existence of the conditional operator makes this harder to read when all one line but it's still an option.

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386634

You could take either the accumulator, if found or concat the element to the accumulator.

const data = ['a', 'b', 'c', 'd', 'a', 'k', 'b'];
const result = data.reduce((a, c) => a.find(e => e === c) ? a : a.concat(c), []);

console.log(result);

Just to mention, Set takes a complete array with the constructor.

const data = ['a', 'b', 'c', 'd', 'a', 'k', 'b'];
const result = Array.from(new Set(data));

console.log(result);

Upvotes: 2

Related Questions