I'm trying to return all the items which broke a relationship in the following array:
[
{ id: "1", option: { bound_id: "2" }},
{ id: "2", option: { bound_id: "12" }},
{ id: "12", option: { bound_id: "2" }}
]
As you can see each item is linked each other using the property bound_id
, if a property broke a relation like:
[
{ id: "1", option: { bound_id: null }},
{ id: "2", option: { bound_id: "12" }},
{ id: "12", option: { bound_id: "2" }}
]
the following result is returned:
[
{ id: "2", option: { bound_id: "12" }}
{ id: "12", option: { bound_id: "2" }}
]
I'm using the following code:
const input = [
{ id: "1", option: { bound_id: null }},
{ id: "2", option: { bound_id: "12" }},
{ id: "12", option: { bound_id: "2" }}
];
const output = input.filter(a => a.option.bound_id);
console.log(output);
I want to include is to insert only the relationship of the items which are next, an example is better:
[
{ id: "1", option: { bound_id: "2" }},
{ id: "2", option: { bound_id: "3" }},
{ id: "12", option: { bound_id: "2" }}
]
as you can see the item with id 2
broke the relation with id 12
and point to an item with id 3
that doesn't exist in the collection, in this scenario the output should be:
[
{ id: "1", option: { bound_id: "2" }},
{ id: "2", option: { bound_id: "3" }}
]
how can I do this using filter?
While using .filter
, you might add to a Set
of the id
s, and .filter
by whether the bound_id
being iterated over is included in the Set
yet (if not, add it to the set; if so, have the item fail the .filter
test). Also keep the item if the index is 0, since you always want to keep the first record:
const input = [
{ id: "1", option: { bound_id: "2" }},
{ id: "2", option: { bound_id: "3" }},
{ id: "12", option: { bound_id: "2" }}
];
const alreadyHave = new Set();
const filtered = input.filter(({ option }, index) => {
const { bound_id } = option;
if (!alreadyHave.has(bound_id) || index === 0) {
alreadyHave.add(bound_id);
return true;
}
});
console.log(filtered);
If, per comment, you actually want to always remove the first item, then change the condition to && index !== 0
:
const input = [
{ id: "1", option: { bound_id: "2" }},
{ id: "2", option: { bound_id: "3" }},
{ id: "12", option: { bound_id: "2" }}
];
const alreadyHave = new Set();
const filtered = input.filter(({ option }, index) => {
const { bound_id } = option;
if (!alreadyHave.has(bound_id) && index !== 0) {
alreadyHave.add(bound_id);
return true;
}
});
console.log(filtered);
Or, per comment, if the logic for the first item should be the same, remove the index
condition entirely:
const input = [
{ id: "1", option: { bound_id: "2" }},
{ id: "2", option: { bound_id: "3" }},
{ id: "12", option: { bound_id: "2" }}
];
const alreadyHave = new Set();
const filtered = input.filter(({ option }, index) => {
const { bound_id } = option;
if (!alreadyHave.has(bound_id)) {
alreadyHave.add(bound_id);
return true;
}
});
console.log(filtered);
My proposal is based on cross checking:
const input1 = [
{ id: "1", option: { bound_id: null }}
];
const input2 = [
{ id: "1", option: { bound_id: "2" }},
{ id: "2", option: { bound_id: "3" }},
{ id: "12", option: { bound_id: "2" }}
];
const input3 = [
{ id: "1", option: { bound_id: null }},
{ id: "2", option: { bound_id: "12" }},
{ id: "12", option: { bound_id: "2" }}
];
const input4 = [
{ id: "1", option: { bound_id: "2" }},
{ id: "2", option: { bound_id: "12" }},
{ id: "12", option: { bound_id: "2" }}
];
var f = (arr) => {
if (arr.length == 1)
return arr;
return arr.filter(function (e, i, a) {
return (!!a[i+1] && e.option.bound_id == a[i+1].id) ||
(!!a[i-1] && e.id == a[i-1].option.bound_id);
})
};
console.log(f(input1));
console.log(f(input2));
console.log(f(input3));
console.log(f(input4));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With