Как удалить пары объектов из массива?(не удаление дубликатов)
Я перерыл весь интернет и не нашел решение, я перечитал все страницы на стековефлоу, хабре Есть варианты только удаление ДУБЛИКАТОВ, что мне не подходит(мне не надо оставлять одно уникальное значение)
let data = [
{'time': '21:30'},
{'time': '21:30'},
{'time': '21:30'},
{'name': 'ivan'},
{'name': 'ivan'}
]
я хочу удалять элементы из массива если они одинаковые если у меня в массиве есть {'name': 'ivan'} и ему соответствующая пара {'name': 'ivan'}, оба удаляются ожидаю на выходе массив
let data = [
{'time': '21:30'},
]
Ответы (4 шт):
Можно так попробовать. Проверяем на четность количество одинаковых элементов. Если нечетное, значит элемент попадает в новый массив.
let data = [
{'time': '21:30'},
{'time': '21:30'},
{'time': '21:30'},
{'name': 'ivan'},
{'name': 'ivan'},
]
let new_data = data.reduce((s,e,i,a) => {
if (!s.some(el => JSON.stringify(e) == JSON.stringify(el))) {
if (a.filter(item => JSON.stringify(item) == JSON.stringify(e)).length%2 != 0) s.push(e);
return s;
}
return s;
},[])
console.log(new_data)
Вы можете обьявить новый пустой массив, далее сделать итерацию по старому объекту на признак нахождения пары для каждого элемента -> Если пара есть - записать в новый массив объектов, а в старом удалить эти 2 объекта
У метода с JSON.stringify есть некоторые ограничения. Например, если свойства объектов идут не в одном порядке, то сравнение вернёт false.
let data = [
{'time': '21:30'},
{'time': '21:30'},
{'time': '21:30'},
{'name': 'ivan'},
{'name': 'ivan'},
{
'a':'x',
'name': 'ivan'
},
{
'name': 'ivan',
'a':'x'
}
]
let new_data = data.reduce((s,e,i,a) => {
if (!s.some(el => JSON.stringify(e) == JSON.stringify(el))) {
if (a.filter(item => JSON.stringify(item) == JSON.stringify(e)).length%2 != 0) s.push(e);
return s;
}
return s;
},[])
console.log(new_data)
console.log(selection(data))
function selection(arr) {
var res = [];
var index = [];
for (i = 0; i < arr.length - 1; i++)
for (j = i + 1; j < arr.length; j++)
if (!index.includes(i) && !index.includes(j) && isEqual(arr[i], arr[j]))
index.push(i, j);
for (var i = 0; i < arr.length; i++)
if (!index.includes(i) && !index.includes(i))
res.push(arr[i]);
return res
}
function isEqual(object1, object2) {
const props1 = Object.getOwnPropertyNames(object1);
const props2 = Object.getOwnPropertyNames(object2);
if (props1.length !== props2.length) {
return false;
}
for (let i = 0; i < props1.length; i += 1) {
const prop = props1[i];
const bothAreObjects = typeof(object1[prop]) === 'object' && typeof(object2[prop]) === 'object';
if ((!bothAreObjects && (object1[prop] !== object2[prop])) ||
(bothAreObjects && !isEqual(object1[prop], object2[prop]))) {
return false;
}
}
return true;
}
Хочу тоже предложить пару вариантов. Первое решение на основе хеш-таблицы. Заполняем таблицу и следом простейший фильтр по четности. Быстрее не могу себе представить:
let data = [
{'time': '21:30'},
{'time': '21:30'},
{'time': '21:30'},
{'name': 'ivan'},
{'name': 'ivan'},
];
let hashes = {};
for (let i = 0; i < data.length; i++) {
let key = JSON.stringify(data[i]);
hashes.hasOwnProperty(key) ? hashes[key] ^= 1 : hashes[key] = 1;
}
let result = data.filter(e => hashes[JSON.stringify(e)]-- > 0);
console.log(result);
Второе решение основано на сравнении двух соседних элементов, поэтому требуется предварительная сортировка:
let data = [
{'time': '21:30'},
{'time': '21:30'},
{'time': '21:30'},
{'name': 'ivan'},
{'name': 'ivan'},
];
let result = [];
let odd = true;
data.sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
let last = data.reduce(function(a, b) {
if (JSON.stringify(a) == JSON.stringify(b)) odd = !odd;
else odd ? result.push(a) : odd = true;
return b;
});
if (odd) result.push(last);
console.log(result);