У меня есть массив таких объектов:
const result = [
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Lemon', Origin: 'Spain' },
{ ProductName: 'Avocado', Origin: 'Chile' }
];
// Expected output since there are duplicates:
const output = [{ ProductName: 'Orange', Origin: 'Italy' }]
Как показано выше, в массиве могут быть дубликаты (но это не обязательно). Вот почему я хотел бы:
К настоящему времени я попытался изменить код, который делает обратное: он находит уникальные (не повторяющиеся) объекты в массиве результатов. Но я просто не могу заставить его работать. Может быть, это просто неправильный подход? Любая помощь приветствуется!
const endresult = result
.map(e => e.ProductName)
.map((e, i, final) => final.indexOf(e) === i && i)
.filter(e => result[e])
.map(e => result[e]);
Пожалуйста, покажите ожидаемый результат. Вы ожидаете out = [{ ProductName: 'Orange', Origin: 'Italy' }]
или out = [{ ProductName: 'Orange', Origin: 'Italy' },{ ProductName: 'Lemon', Origin: 'Spain' },{ ProductName: 'Avocado', Origin: 'Chile' }]
@pilchard: ожидаемый результат: out = [{ ProductName: 'Orange', Origin: 'Italy' }]
Вот решение с использованием уменьшить:
const result = [
{ProductName: "Orange", Origin: "Italy"},
{ProductName: "Orange", Origin: "Italy"},
{ProductName: "Lemon", Origin: "Spain"},
{ProductName: "Avocado",Origin: "Chile"},
{ProductName: "Orange", Origin: "Italy"}
];
function getDuplicatesOrAll(arr) {
const duplicates = arr
.reduce((acc, p, i) => {
const isDuplicate = i !== result.findIndex(({ProductName}) => ProductName === p.ProductName);
if (isDuplicate) {
const wasAlreadyMet = acc.some(({ProductName}) => ProductName === p.ProductName);
if (!wasAlreadyMet) {
acc.push(p);
}
}
return acc;
}, []);
return duplicates.length ? duplicates : arr;
}
console.info( getDuplicatesOrAll(result) );
Возможно, проще читать, используя ваш метод для работы только с именами:
const result = [
{ProductName: "Orange", Origin: "Italy"},
{ProductName: "Orange", Origin: "Italy"},
{ProductName: "Lemon", Origin: "Spain"},
{ProductName: "Avocado",Origin: "Chile"},
{ProductName: "Orange", Origin: "Italy"}
];
function getDuplicatesOrAll(arr) {
const duplicates = arr
.map(({ProductName}) => ProductName)
.reduce((acc, name, i, final) => {
const isDuplicate = i !== final.indexOf(name);
if (isDuplicate) {
const wasAlreadyMet = acc.includes(name);
if (!wasAlreadyMet) {
acc.push(name);
}
}
return acc;
}, [])
.map(name => result.find(({ProductName}) => ProductName === name));
return duplicates.length ? duplicates : arr;
}
console.info( getDuplicatesOrAll(result) );
Итак, все работает, когда у меня есть дубликаты в массиве результатов. Но когда нет дубликатов, я получаю пустой массив. Я полагаю, нам нужно включить дополнительный оператор if-else? Что вы думаете?
@Ewax_Du Я пропустил эту часть. Я отредактировал код и сделал функцию, содержащую эту логику.
Спасибо. Я проверил код, и он работает. Я отметил ваш ответ как решение, потому что вы дали мне 2 возможных фрагмента кода, и это облегчило мне - как новичку - следование. Еще раз спасибо!
Создайте два объекта из уникальных элементов и дубликатов, затем проверьте, существует ли дубликат, сделайте его массивом и верните его.
const result = [
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Lemon', Origin: 'Spain' },
{ ProductName: 'Avocado', Origin: 'Chile' }
];
function duplicateFinder(array){
const cache = {};
const duplicates = {};
let endResult = [];
array.forEach(e=>{
cache[e.Origin]?
duplicates[e.Origin] = e:
cache[e.Origin] = true;
})
Object.keys(duplicates).forEach(e => {
endResult.push(duplicates[e])
})
return endResult.length ? endResult : array;
}
console.info(duplicateFinder(result))
Можно выполнить с помощью Array#filter
и Array#some
.
Array#filter
, и для каждого объекта проверьте, повторяется ли этот объект.Array#some
.const result = [
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Lemon', Origin: 'Spain' },
{ ProductName: 'Avocado', Origin: 'Chile' },
];
const getDups = (arr) => {
const seen = new Set
const dups = arr
.filter((o1, i)=> arr.slice(i+1)
.some(o2 => o1.ProductName === o2.ProductName &&
o1.Origin === o2.Origin)
&&
!arr.slice(0, i)
.some(o2 => o1.ProductName === o2.ProductName &&
o1.Origin === o2.Origin));
if (dups.length){
return dups;
}
return arr;
}
console.info(getDups(result));
@blex спасибо, что заметили эту ошибку, исправил ее сейчас!
Вы можете сделать это, используя методы Array.prototype.sort()
и Array.prototype.filter()
.
ProductName
.const result = [
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Orange', Origin: 'Italy' },
{ ProductName: 'Lemon', Origin: 'Spain' },
{ ProductName: 'Avocado', Origin: 'Chile' },
];
let ret = result
.sort((x, y) => x.ProductName.localeCompare(y.ProductName))
.filter((x, i, a) => i > 0 && x.ProductName === a[i - 1].ProductName);
if (!ret.length) ret = result;
console.info(ret);
const result=[{ProductName:"Orange",Origin:"Italy"},{ProductName:"Orange",Origin:"Italy"},{ProductName:"Lemon",Origin:"Spain"},{ProductName:"Avocado",Origin:"Chile"}];
const findDuplicates = (arr) => {
let result =[]
arr.forEach((e,i) => {
let slice = arr.slice(i+1)
let dupl = slice.find(n => (n.ProductName === e.ProductName) && (n.Origin === e.Origin))
if (dupl){
if (!result.find(n => (n.ProductName === dupl.ProductName) && (n.Origin === dupl.Origin))){
result.push(dupl)
}
}
})
return result
}
console.info(findDuplicates(result))
Перебрать каждый элемент (вы можете игнорировать последний) и для каждого элемента проверить все элементы, которые идут после него (требуется второй цикл), если есть объект с тем же продуктом. Если это так, поместите этот элемент в новый массив (необходима проверка, есть ли уже объект с таким же продуктом). В конце у вас либо массив повторяющихся значений, либо пустой, потому что в источнике нет дубликатов.