1

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!

2
  • 1
    This is actually tougher than it seems as your intros and exits is an object instead of an ordered array. Should we be assuming that intro and exit entries will always end in _index, e.g. exit_0. I assume as well 0 is your starting index in naming these entries? If you created this structure I would suggest in future using an array of objects. Commented Apr 27, 2020 at 12:24
  • @DaneBrouwer all "intros" and "exits" end in an ordered index starting with 0. It's the only guide I saw. The data was given to me. I figured it wouldn't be that easy because I couldn't find any method to remove what I wanted directly Commented Apr 27, 2020 at 12:33

1 Answer 1

2

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)

Sign up to request clarification or add additional context in comments.

9 Comments

This will not work if you have an array in your data. Then you could either modify original data or use some deepClone method and then modify that clone object.
you could just edit your answer to include your comment :)
@NenadVracar I'm checking your solution but "const check = props.some(p => Object.keys(v).includes(p))" I get an error back "Cannot convert undefined or null to object"
I am guessing you are trying on some other data, can you post it?
At some point v is null or undefined, that is why you get the error.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.