У меня есть массив массивов, который должен стать 1 массивом уникальных значений.
[1, 3, 2], [5, 2, 1, 4], [2, 1]
Я хочу использовать reduce / map для решения проблемы, но похоже, что это не работает. Я решил проблему уже с вложенными циклами for, например:
function uniteUnique(arr) {
var args = Array.from(arguments);
var arr = [];
for (var i = 0; i < args.length; i++) {
for (var j = 0; j < args[i].length; j++) {
if (!arr.includes(args[i][j])) {
arr.push(args[i][j]);
}
}
}
return arr;
}
Теперь я попытался решить проблему с помощью reduce / map, но не получил правильного решения, например:
function uniteUnique(arr) {
var args = Array.from(arguments);
return args.reduce(
(arr, a) => a.map(n => (!arr.includes(n) ? arr.push(n) : n)),
[]
);
}
console.info(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]));
Я также попытался решить с помощью reduce / map, используя старый синтаксис, например:
function uniteUnique(arr) {
var args = Array.from(arguments);
return args.reduce(function(arr, a) {
return a.map(function(n) {
if (!arr.includes(n)) {
return arr.push(n);
} else {
return n;
}
});
});
}
Я предполагаю, что я что-то не делаю правильно с операторами return в функциях обратного вызова. Любая помощь будет оценена, спасибо.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема в том, что:
arr.includes(n)
arr - это массив массивов, включает в себя не работает. Вы также никогда не пропускаете arr вниз по цепочке сокращения.
Проще всего решить:
[...new Set(array.reduce((a, b) => a.concat(b), []))]
Это просто сглаживает массив, создает набор для уникальности и распределяет его в массив. Или другое элегантное решение с использованием итераторов:
function* flatten(arr) {
for(const el of arr) {
if (Array.isArray(el)) {
yield* flatten(el);
} else {
yield el;
}
}
}
const result = [];
for(const el of flatten(array))
if (!result.includes(el)) result.push(el);
На самом деле я думаю, что arr - это мой пустой массив, объявленный в начальном сокращении, тогда как args - это мой массив массивов.
@ jhazelton1 да ты прав. Вы запутали меня странным аргументом функции.
Вместо использования array#map используйте array#forEach и вставьте уникальный номер в аккумулятор.
function uniteUnique(arr) {
var args = Array.from(arguments);
return args.reduce((arr, a) => {
a.forEach(n => (!arr.includes(n) ? arr.push(n) : n));
return arr
},[]);
}
console.info(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]));В качестве альтернативы вы можете array#concat весь массив, а затем с помощью Set получить уникальное значение.
const arr = [[1, 3, 2], [5, 2, 1, 4], [2, 1]],
unique = [...new Set([].concat(...arr))];
console.info(unique);Можете ли вы объяснить, почему здесь работает array # forEach вместо array # map?
Даже array#map работал бы, но array#map возвращал новое значение для каждой итерации, которая перезаписывала старый результат. Итак, что вам нужно, это аккумулятор и проверка вашего числа относительно этого аккумулятора. Итак, вместо того, чтобы возвращать результат array#map, вам нужно было вернуть значение аккумулятора.
не могли бы вы добавить немного пояснений, ваше решение выглядит действительно красиво и коротко