Reputation: 865
I have the following nested object:
{
"cards": {
"1": {
"x": 247,
"y": 213,
"properties": {
"id": 1,
"name": "a",
"intros": {
"intro_0": {
"id": 1,
"cardId": 1
},
"intro_1": {
"id": 2,
"cardId": 1
},
"intro_3": {
"id": 24,
"cardId": 1
}
},
"exits": {
"exit_0": {
"id": 1,
"cardId": 1
},
"exit_1": {
"id": 22,
"cardId": 1
}
},
"mixins": {
"mixin_0": {
"id": 23,
"cardId": 1
}
}
}
},
"3": {
"x": 762,
"y": 187,
"properties": {
"id": 1,
"name": "x",
"intros": {
"intro_0": {
"id": 1,
"cardId": 1
},
"intro_1": {
"id": 263,
"cardId": 1
}
},
"exits": {
"exit_0": {
"id": 1,
"cardId": 1
},
"exit_1": {
"id": 2,
"cardId": 1
}
},
"mixins": {
"mixin_0": {
"id": 3,
"cardId": 1
}
},
}
},
"4": {
"x": 1200,
"y": 187,
"properties": {
"id": 1,
"name": "j",
"intros": {
"intro_0": {
"id": 1,
"cardId": 1
},
"intro_1": {
"id": 276,
"cardId": 1
}
},
"exits": {
"exit_0": {
"id": 1,
"cardId": 1
},
"exit_1": {
"id": 2,
"cardId": 1
}
},
"mixins": {
"mixin_0": {
"id": 3,
"cardId": 1
}
}
}
}
}
}
I am trying to go through the object to extract only the first of the "intro" and the first of the "exit" and modify the original object so that it only contains these with the rest of the data. Or what is the same, I would like to remove all the "intros" except the first one and all the "exits" except the first one. To extract the values I want I have made 3 for in ... but when it comes to modifying the original object I think I've made it too complicated and there must be some easier way.
const cards: any = Object.values(data.cards);
for (const indexCard in cards) {
if (cards.hasOwnProperty(indexCard)) {
const card = cards[indexCard];
const cardIntros = card.properties.intros;
for (const introIndex in cardIntros) {
if (cardIntros.hasOwnProperty(introIndex) && introIndex === 'intro_0') {
const firstIntro = cardIntros[introIndex];
const cardsExits = card.properties.exits;
for (const exitIndex in cardsExits) {
if (cardsExits.hasOwnProperty(exitIndex) && exitIndex === 'exit_0') {
const firstExit = cardsExits[exitIndex];
}
}
}
}
}
}
Does anyone see an easier way to remove the "intros" and "exits" I want to remove, in order to generate a new object that only contains the desired "intros" and "exits"?
Thank you in advance!
Upvotes: 1
Views: 162
Reputation: 122037
You could create recursive function that will check if the current value is object and then also if the some of the keys of that object is equal to the keys provided by the parameter. If it does include that key it will delete other keys from that object. This will work for any level of nesting.
const data = {"cards":{"1":{"x":247,"y":213,"properties":{"id":1,"name":"a","intros":{"intro_0":{"id":1,"cardId":1},"intro_1":{"id":2,"cardId":1},"intro_3":{"id":24,"cardId":1}},"exits":{"exit_0":{"id":1,"cardId":1},"exit_1":{"id":22,"cardId":1}},"mixins":{"mixin_0":{"id":23,"cardId":1}}}},"3":{"x":762,"y":187,"properties":{"id":1,"name":"x","intros":{"intro_0":{"id":1,"cardId":1},"intro_1":{"id":263,"cardId":1}},"exits":{"exit_0":{"id":1,"cardId":1},"exit_1":{"id":2,"cardId":1}},"mixins":{"mixin_0":{"id":3,"cardId":1}}}},"4":{"x":1200,"y":187,"properties":{"id":1,"name":"j","intros":{"intro_0":{"id":1,"cardId":1},"intro_1":{"id":276,"cardId":1}},"exits":{"exit_0":{"id":1,"cardId":1},"exit_1":{"id":2,"cardId":1}},"mixins":{"mixin_0":{"id":3,"cardId":1}}}}}}
function first(data, props = []) {
return Object.entries(data).reduce((r, [k, v]) => {
if (typeof v == 'object' && v != null) {
if (Array.isArray(v)) {
r[k] = v.map(e => first(e, props))
} else {
const value = { ...v }
const check = props.some(p => Object.keys(v).includes(p))
if (check) {
for (let i in value) {
if (!props.includes(i)) {
delete value[i]
}
}
}
r[k] = first(value, props)
}
} else r[k] = v
return r;
}, {})
}
const result = first(data, ['intro_0', 'exit_0'])
console.log(result)
Upvotes: 2