Допустим, у меня есть два массива следующим образом:
const A = ['Mo', 'Tu', 'We', 'Thu', 'Fr']
const B = ['Mo', 'Mo', 'Mo', 'Tu', 'Thu', 'Fr', 'Sa']
Я хочу вычесть массив A из массива B. Результат выглядит следующим образом:
const result = ['Mo', 'Mo', 'Sa']
Как этого добиться? Это кажется таким простым, но я не могу заставить его работать.
По сути, это должно удалить все из B, как только это будет в A.
Как упомянул @jarmod, ответ находится в этом посте, проверьте этот ответ: stackoverflow.com/a/36504668/7560262
Выполнение разницы в наборе не будет содержать дубликатов в результате, поскольку набор не может иметь дубликатов по своей природе.



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


Попробуй это:
const A = ['Mo', 'Tu', 'We', 'Thu', 'Fr']
const B = ['Mo', 'Mo', 'Mo', 'Tu', 'Thu', 'Fr', 'Sa']
let res = B;
A.forEach(val => {
for(let i = 0; i < res.length; i++) {
if (res[i] === val) {
res.splice(res.indexOf(val), 1);
break;
}
}
});
Это мутирует B. Замените let res = B; на const res = B.slice();.
const A = ['Mo', 'Tu', 'We', 'Thu', 'Fr']
const B = ['Mo', 'Mo', 'Mo', 'Tu', 'Thu', 'Fr', 'Sa']
console.info(A.reduce((b, a)=>
(b.includes(a) && b.splice(b.indexOf(a),1), b), [...B]))Без кода гольф:
const A = ['Mo', 'Tu', 'We', 'Thu', 'Fr']
const B = ['Mo', 'Mo', 'Mo', 'Tu', 'Thu', 'Fr', 'Sa']
console.info(A.reduce((b, a)=> {
if (b.includes(a)) b.splice(b.indexOf(a), 1); return b; }, [...B]))Возможно, придется перефразировать мой заголовок, чтобы было легче понять тип проблемы.
@TomelSafadi моя первая попытка изменила A на месте. Я только что обновил ответ, чтобы вернуть желаемый результат, сохранив при этом состояние A и B.
Вы знаете, почему я получаю ошибку eslint для переменной b при любом изменении? Unexpected use of comma operator
@TomelSafadi Потому что ESLint не любит оператор запятой с включенным правилом no-sequences. Смотрите документацию. Вместо этого вы можете использовать A.reduce((b, a) => { if (b.includes(a)){ b.splice(b.indexOf(a), 1); } return b; }, B.slice()), чтобы не использовать этот синтаксис в стиле codegolf.
@TomelSafadi обычно это полезное предупреждение, которое может спасти вас, если вы неправильно поставили запятую и не хотели создавать выражение запятой. Однако мы намеревались использовать запятую. Если это вас беспокоит, вы можете удалить предупреждение, изменив его на это: console.info(A.reduce((b, a)=>b.includes(a) && b.splice(b.indexOf(a),1) && b || b, [...B]))
const A = ['Mo', 'Tu', 'We', 'Thu', 'Fr']
const B = ['Mo', 'Mo', 'Mo', 'Tu', 'Thu', 'Fr', 'Sa']
const C = B.map(el => {
const elIndexInA = A.findIndex(e => e === el)
if (elIndexInA === -1) {
return el
}
A.splice(elIndexInA, 1)
}).filter(el => el)
console.info(C)Это мутирует A. Введите const res = A.slice(); и замените каждый A на res.
Это также не работает для A = [ undefined ]; B = [ undefined, undefined ];. Должно быть [ undefined ], но у вас получается []. Еще один неудачный тест: A = [ 1 ]; B = [ undefined, undefined ] (должно быть [ undefined, undefined ]).
@SebastianSimon хорошо, мой ответ связан с фрагментом кода в вопросе, вы можете настроить его для своих нужд, я почти уверен, что в большинстве случаев вы не вернете undefined как значение
Забавный маленький filter() над картой А.
const A = ['Mo', 'Tu', 'We', 'Thu', 'Fr']
const B = ['Mo', 'Mo', 'Mo', 'Tu', 'Thu', 'Fr', 'Sa']
const aMap = A.reduce((a, c) => (a[c] = (a[c] ?? 0) + 1, a), {})
const result = B.filter(n => !(aMap[n]-- > 0))
console.info(result)
Связанное, но не совсем одно и то же: Какой самый быстрый или самый элегантный способ вычислить разницу между наборами с использованием массивов Javascript?