I have an array like this:
const data = [
{"id": 3, "value": "a"},
{"id": 3, "value": "b"},
{"id": 4, "value": "a"},
{"id": 8, "value": "d"},
{"id": 1, "value": "d"},
{"id": 2, "value": "d"},
{"id": 5, "value": "z"},
{"id": 8, "value": "h"},
{"id": 8, "value": "b"},
]
and would like to delete all objects, where the value is not the same in one of the other objects. So, at the end I would like to have:
[
{"id": 3, "value": "a"},
{"id": 4, "value": "a"},
{"id": 3, "value": "b"},
{"id": 8, "value": "b"},
{"id": 1, "value": "d"},
{"id": 2, "value": "d"},
]
I tried several versions. How to check against something which you don´t know if it is there (later in the loop)? If I do check the list against itself in a loop, I am runing in the corner, that the array itself changes its length during the for loop... Is there a simple approach?
Thanks for any help!
CodePudding user response:
You need two passes in your array: the first one will count the number for each values, the second one will remove the objects with lone values:
function removeLoneValues(data) {
const values = {}
data.forEach(datum => {
if (values[datum.value] === undefined) {
values[datum.value] = 0
}
values[datum.value]
})
data.filter(datum => {
return values[datum.value] > 1
})
return data
}
CodePudding user response:
You can achieve it like this:-
const data = [
{"id": 3, "value": "a"},
{"id": 3, "value": "b"},
{"id": 4, "value": "a"},
{"id": 8, "value": "d"},
{"id": 1, "value": "d"},
{"id": 2, "value": "d"},
{"id": 5, "value": "z"},
{"id": 8, "value": "h"},
{"id": 8, "value": "b"},
]
let reqOutput = [];
for (let i = 0; i < data.length; i ) {
if (data[i].value == "a") {
reqOutput.push(data[i]);
}
}
for (let i = 0; i < data.length; i ) {
if (data[i].value == "b") {
reqOutput.push(data[i]);
}
}
for (let i = 0; i < data.length; i ) {
if (data[i].value == "d") {
reqOutput.push(data[i]);
}
}
console.log(reqOutput);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You can use Array.prototype.indexOf
and Array.prototype.lastIndexOf
alongside Array.prototype.filter
and Array.prototype.map
to achieve this:
const data = [
{"id": 3, "value": 'a'},
{"id": 3, "value": 'b'},
{"id": 4, "value": 'a'},
{"id": 8, "value": 'd'},
{"id": 1, "value": 'd'},
{"id": 2, "value": 'd'},
{"id": 5, "value": 'z'},
{"id": 8, "value": 'h'},
{"id": 8, "value": 'b'},
];
const values = data.map((el) => el.value);
const nonUniqueData = data.filter((el) => values.indexOf(el.value) !== values.lastIndexOf(el.value));
console.log(nonUniqueData);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
This code works by first creating a mapped array of only values, then by checking that the results of indexOf
and lastIndexOf
when finding that value in the mapped array are different we can check that the array is not unique. This heuristic is then used in a filter function to create a new version of your data
array with all elements containing unique values removed.
If you need to sort your array based on its value, you can use Array.prototype.sort
to do that based on whatever your values are. I've converted them to strings here so the code snippet will run.