I have a very simple array:
var arr = [{id: 1, score: 10}, {id: 1, score: 10}, {id: 3, score: 20}, {id: 4, score: 5}];
I want to remove those object which has only single occurrence e.g:
{id: 3, score: 20}
{id: 4, score: 5}
So the final output should be:
[{id: 1, score: 10}, {id: 1, score: 10}]
What I have tried so far is:
const result = [];
for (let i = 0; i < arr.length; i ) {
for (let j = i 1; j < arr.length; j ) {
if (arr[i].id === arr[j].id && arr[i].score === arr[j].score) {
result.push({ id: arr[i].id, score: arr[i].score })
}
}
}
But this is removing my duplicates as well, e,g it gives me this result:
[{id: 1, score: 10}]
But i need this result:
[{id: 1, score: 10}, {id: 1, score: 10}]
CodePudding user response:
Array.filter
will help
Filter the array with combination of id
and score
, check if the length of this comination is greater than 1, which means there are more than one occurance of this combination.
const arr = [{ id: 1, score: 10 }, { id: 1, score: 10 }, { id: 3, score: 20 }, { id: 4, score: 5 }, { id: 77, score: 25, type: 'notthisone' }];
const newArr = arr.filter(item => arr.filter(x => x.id === item.id && x.score === item.score).length > 1 || item.type === 'notthisone');
console.log(newArr);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Your fixes solution.
You have to push the value from arr
for both index i
and j
. But the index node for i
must be pushed only once.
const arr = [{id: 1, score: 10}, {id: 1, score: 10}, {id: 3, score: 20}, {id: 4, score: 5}, {id: 77, score: 25, type: 'notthisone'}];
const result = [];
for (let i = 0; i < arr.length; i ) {
let isFound = false;
for (let j = i 1; j < arr.length; j ) {
if (arr[i].id === arr[j].id && arr[i].score === arr[j].score) {
isFound = true;
result.push(arr[j]);
}
}
if(isFound || arr[i].type === 'notthisone') {
result.push(arr[i]);
}
}
console.log(result);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Edit: If you want to have one specific object having particular value for key type
, then you can include that in the condition. I have updated the answer with that.
CodePudding user response:
You could take a single loop and an object for keeping track of the first of reference for the same item.
const
array = [{ id: 1, score: 10, x: 1 }, { id: 1, score: 10, x: 2, }, { id: 3, score: 20 }, { id: 4, score: 5 }, { id: 77, score: 25, type: 'notthisone' }],
getKey = ({ id, score }) => JSON.stringify({ id, score }),
result = array
.map((q => o => {
if (o.type === 'notthisone') return o;
const
key = getKey(o),
target = [];
q[key] ??= { value: undefined, target };
if (q[key].value) {
q[key].target[0] ??= q[key].value;
return o;
}
q[key].value = o;
return target;
})({}))
.flat();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You may consider using Array.reduce
combined with Array.find
(Array.find
is less 'expensive' than Array.filter
). Something like (also took your question on @Nitheesh' answer into account):
const arr = [
{id: 1, score: 10},
{id: 1, score: 10},
{id: 3, score: 20},
{id: 4, score: 5},
{id: 77, score: 25, include: true} ];
const log = document.querySelector(`pre`);
log.textContent = `**Reduced\n${
JSON.stringify(retrieveDuplicates(arr), null, 2)}`;
log.textContent = `\n\n**Looped\n${
JSON.stringify(retrieveDuplicatesLoop(arr), null, 2)}`;
// reducer
function retrieveDuplicates(arr) {
return arr.reduce( ( acc, v, i ) => {
const exists = v.include ? v :
arr.slice(i 1).find( vv => v.id === vv.id && v.score === vv.score );
acc = !acc.length && exists ? acc.concat({...v}) : acc;
return exists ? [...acc, {...exists}] : acc;
}, [] );
}
// Or in a classic loop
function retrieveDuplicatesLoop(arr) {
let result = [];
for (let i = 0; i < arr.length; i = 1) {
const exist = arr[i].include ? arr[i] :
arr.slice(i 1).find(v => arr[i].id === v.id && arr[i].score === v.score);
if (!result.length && exist) { result.push(arr[i]); }
result = exist && result.concat(arr[i]) || result;
}
return result;
}
<pre></pre>
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>