简体   繁体   中英

Finding a match between nested values in objects and arrays

I have two arrays:

In the first, I have an array of objects that contain a persons information, and an array which contains selections they have made from a list of categories.

In the second, I have an array of objects that contain the categories a person from the first array could have made selections from. Inside each of the category objects there is a category title, and a selections array which I would like to contain a list of the players who have selected this category.

I need to render elements in my ui based on the number of people who have selected a category, for every category. I am wondering if it is possible for me to iterate through a persons selections from the first array, which has the category title, find the matching category title in the second array and push that persons information from the first array into the selections array in the second one.

I am definitely open to restructuring these arrays, but the second one has a lot more information, not relevant to this problem, and would prefer to leave as is. I have to hardcode the first array, as I am just getting that information from emails being sent to me, I currently have no way of pushing a persons selections into the second array at the time they are being chosen.

An example of what I'm trying to achieve is below.

listOfPeople: [
        {
            personName: 'Eric Smith',
            selections: [
                {
                    categoryTitle: 'Fruit',
                    categoryItem: 'Apple',
                },
                {
                    categoryTitle: 'Animals',
                    categoryItem: 'Dog',
                },
                {
                    categoryTitle: 'Cars',
                    categoryItem: 'Ford'
                },
            ]
        },
        {
            personName: 'Sarah Edwards',
            selections: [
                {
                    categoryTitle: 'Shoes',
                    categoryItem: 'Running Shoe',
                },
                {
                    categoryTitle: 'Animals',
                    categoryItem: 'Cat',
                },
            ]
        }
    ],
    listOfCategories: [
        {
            categoryTitle: 'Fruit',
            peopleWhoSelected: [
                {
                    personName: 'Eric Smith',
                    categoryItem: 'Apple',
                },
            ]
        },
        {
            categoryTitle: 'Animals',
            peopleWhoSelected: [
                {
                    personName: 'Eric Smith',
                    categoryItem: 'Dog',
                },
                {
                    personName: 'Sarah Edwards',
                    categoryItem: 'Cat',
                },
            ]
        },
        {
            categoryTitle: 'Cars',
            peopleWhoSelected: [
                {
                    personName: 'Eric Smith',
                    categoryItem: 'Ford',
                },
            ]
        },
    ]

Here is a simple way of doing it, read the comment to understand

 var listOfPeople = [{personName: 'Eric Smith'}, { personName: 'Sarah Edwards'}] var listOfCategories= [ { categoryTitle: 'Fruit', peopleWhoSelected: [ { personName: 'Eric Smith', categoryItem: 'Apple', }, ] }, { categoryTitle: 'Animals', peopleWhoSelected: [ { personName: 'Eric Smith', categoryItem: 'Dog', }, { personName: 'Sarah Edwards', categoryItem: 'Cat', }, ] }, { categoryTitle: 'Cars', peopleWhoSelected: [ { personName: 'Eric Smith', categoryItem: 'Ford', }, ] }, ] listOfCategories.forEach((cat)=>{ cat.peopleWhoSelected.forEach((s)=> { // find the right person var person = listOfPeople[listOfPeople.findIndex(p=> p.personName == s.personName )]; // check if there is a property selections, if no then add it if (!person.selections) person.selections = []; // if Person dose not already have this categoryItem then add it if (person.selections.findIndex(x=> x.categoryItem == s.categoryItem) ==-1) person.selections.push({ categoryTitle: cat.categoryTitle, categoryItem: s.categoryItem }); }); }); console.log(listOfPeople) 

If you can simplify the first object I would recommend you to do something like this:

const people =
{
  "Eric Smith": {
    "Fruit": "Apple",
    "Animals": "Dog",
    "Cars": "Ford"
  },
  "Sarah Edwards": {
    "Shoes": "Running Shoe",
    "Animals": "Cat"
  }
}

Where you have directly what people have selected.

Then pushing a person's selections into the second array:

Object.entries(people).forEach(([person, categories]) => 
  Object.entries(categories).forEach(([title, item]) => {
    let category = listOfCategories.find(c => c.categoryTitle == title)
    // Create category if we didn't find it
    if (!category) {
      category = {
        categoryTitle: title,
        peopleWhoSelected: []
      }
      listOfCategories.push(category)
    }
    // Add item selected and person name to category
    category.peopleWhoSelected.push({
      personName: person,
      categoryItem: item
    })    
  }))

Here you have a working example (open the console to see the result): https://jsfiddle.net/1pxhvo5k/

Hope this help :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM