Home > Net >  How to check if object keys of an array of objects have the same values ​at different nesting level
How to check if object keys of an array of objects have the same values ​at different nesting level

Time:11-02

I have an array of objects, with nested objects:

const data = [{
    "operationId": "6357a5bba0de053fb601d573",
    "tags": {
        "120": {
            "title": "ac milan",
            "color": "red",
            "updated_at": "2022-10-25 08:52:00",
            "created_at": "2022-10-25 08:52:00",
            "_id": "6357a3b06891976bca0a9215"
        },
        "121": {
            "title": "napoli",
            "color": "blue",
            "updated_at": "2022-10-25 08:54:12",
            "created_at": "2022-10-25 08:54:12",
            "_id": "6357a43470761099ce0049e0"
        },
    }
}, {
    "operationId": "6357a5c9a0de053fb601d574",
    "tags": {
        "118": {
            "title": "ac roma",
            "color": "red",
            "updated_at": "2022-10-25 07:54:19",
            "created_at": "2022-10-25 07:54:19",
            "_id": "6357962b6891976bca0a920e"
        },
        "120": {
            "title": "ac milan",
            "color": "red",
            "updated_at": "2022-10-25 08:52:00",
            "created_at": "2022-10-25 08:52:00",
            "_id": "6357a3b06891976bca0a9215"
        },
    }
}];

where:

  • operationId - id of document;
  • tags - object with binded to document tags.

Based on the information, I need to display a list of tags in the markup. But the same tag can be attached to different documents (as in the example - the "AC Milan" tag is attached to two documents). In this case, the tag must be rendered once. My current iteration of an array of objects does not take this feature into account, and displays everything in a row, but I don’t really understand how to fix it.

function addExistingTagsToModal(arr) {
  let existingTagTitle, existingTagColor, existingTagID;

  const constructedData = arr.map(item => {
    const operationId = item?.operationId;

    const innerValues = Object.values(item.tags);
    return innerValues.map(subItem => {

      existingTagID = subItem._id;
      existingTagTitle = subItem.title;
      existingTagColor = subItem.color;

      let tagObjMarkup = {
        tagMarkup: `<li>${existingTagTitle}</li>`
      };

      let addedTagList = document.querySelector('.list');
      addedTagList.insertAdjacentHTML('afterbegin', tagObjMarkup.tagMarkup);

      return {
        ...subItem,
        operationId
      }
    });
  });
}

addExistingTagsToModal(data);

Here is a working example (Codepen). To summarize: in the code above, AC Milan should be displayed 1 time. How to do it?

CodePudding user response:

You just need to keep track of the existing titles, so I created an object const tagTitleDict = {}; and checking a key already in it. If found a key in tagTitleDict then no need to insert it again in the list <ul></ul>.

function addExistingTagsToModal(arr) {
  let existingTagTitle, existingTagColor, existingTagID;
  const tagTitleDict = {};

  const constructedData = arr.map((item) => {
    const operationId = item?.operationId;

    const innerValues = Object.values(item.tags);
    return innerValues.map((subItem) => {
      existingTagID = subItem._id;
      existingTagTitle = subItem.title;
      existingTagColor = subItem.color;

      if (!(existingTagTitle in tagTitleDict)) {
        let tagObjMarkup = {
          tagMarkup: `<li>${existingTagTitle}</li>`
        };

        let addedTagList = document.querySelector(".list");
        addedTagList.insertAdjacentHTML("afterbegin", tagObjMarkup.tagMarkup);

        tagTitleDict[existingTagTitle] = true;
      }

      return {
        ...subItem,
        operationId
      };
    });
  });
}

Have adjusted to your codepen

Hope it helps, cheers!

  • Related