简体   繁体   中英

How to find a value in a nested array of objects and update it?

I am trying find a value in a nested array of objects and updated it. More specifically, in the array below, I am trying to find the OptionCode based on a String and set the corresponding option to blocked . The search strings are stored in an array.

Inital Array:

filters: [
    {
        FilterCode: "TourPrice",
        FilterName: "Tour Price",
        FilterIcon: show_Dollar,
        Options: [
            {
                Name: "Free",
                OptionCode: "Free",
                active: false,
                blocked: false,
                forbiddenFilterOptionCode: ["LowestPrice"],
            },
            {
                Name: "Paid",
                OptionCode: "Paid",
                active: false,
                blocked: false,
                forbiddenFilterOptionCode: [],
            },
            {
                Name: "Free and Paid",
                OptionCode: "FreeAndPaid",
                active: true,
                blocked: false,
                forbiddenFilterOptionCode: [],
            },
        ],
    },
    {
        FilterCode: "SortedBy",
        FilterName: "Sorted By",
        FilterIcon: show_Sort,
        Options: [
            {
                Name: "Most Relevant",
                OptionCode: "MostRelevant",
                active: true,
                blocked: false,
                forbiddenFilterOptionCode: [],
            },
            {
                Name: "Latest Tour",
                OptionCode: "LatestTour",
                active: false,
                blocked: false,
                forbiddenFilterOptionCode: [],
            },
            {
                Name: "Oldest Tour",
                OptionCode: "OldestTour",
                active: false,
                blocked: false,
                forbiddenFilterOptionCode: [],
            },
            {
                Name: "Lowest Price",
                OptionCode: "LowestPrice",
                active: false,
                blocked: false,
                forbiddenFilterOptionCode: ["Free", "FreeAndPaid],
            },
        ],
    },
],

For the following search input ["Free", "FreeAndPaid"] the following array is expected.

Intended Result Array

filters: [
    {
        FilterCode: "TourPrice",
        FilterName: "Tour Price",
        FilterIcon: show_Dollar,
        Options: [
            {
                Name: "Free",
                OptionCode: "Free", // Find OptionCode
                active: false,
                blocked: true, // set blocked to true
                forbiddenFilterOptionCode: ["LowestPrice"],
            },
            {
                Name: "Paid",
                OptionCode: "Paid",
                active: false,
                blocked: false,
                forbiddenFilterOptionCode: [],
            },
            {
                Name: "Free and Paid",
                OptionCode: "FreeAndPaid", // Find OptionCode
                active: true,
                blocked: true, // set blocked to true
                forbiddenFilterOptionCode: [],
            },
        ],
    },
    {
        FilterCode: "SortedBy",
        FilterName: "Sorted By",
        FilterIcon: show_Sort,
        Options: [
            {
                Name: "Most Relevant",
                OptionCode: "MostRelevant",
                active: true,
                blocked: false,
                forbiddenFilterOptionCode: [],
            },
            {
                Name: "Latest Tour",
                OptionCode: "LatestTour",
                active: false,
                blocked: false,
                forbiddenFilterOptionCode: [],
            },
            {
                Name: "Oldest Tour",
                OptionCode: "OldestTour",
                active: false,
                blocked: false,
                forbiddenFilterOptionCode: [],
            },
            {
                Name: "Lowest Price",
                OptionCode: "LowestPrice",
                active: false,
                blocked: false,
                forbiddenFilterOptionCode:  ["Free", "FreeAndPaid"],
            },
        ],
    },
],

You could use the function below. I made filters a variable, as it is not clear from your question what object it is a property of.

The solution is to iterate the array, then iterate the option objects, and finally detect whether that object's OptionCode value is among your targeted values.

The filters structure is thus modified in place :

 function setBlocked(filters, target) { for (let filter of filters) { for (let option of filter.Options) { if (target.includes(option.OptionCode)) { option.blocked = true; } } } } let filters = [{FilterCode: "TourPrice",FilterName: "Tour Price",FilterIcon: "show_Dollar",Options: [{Name: "Free",OptionCode: "Free",active: false,blocked: false,forbiddenFilterOptionCode: ["LowestPrice"],},{Name: "Paid",OptionCode: "Paid",active: false,blocked: false,forbiddenFilterOptionCode: [],},{Name: "Free and Paid",OptionCode: "FreeAndPaid",active: true,blocked: false,forbiddenFilterOptionCode: [],},],},{FilterCode: "SortedBy",FilterName: "Sorted By",FilterIcon: "show_Sort",Options: [{Name: "Most Relevant",OptionCode: "MostRelevant",active: true,blocked: false,forbiddenFilterOptionCode: [],},{Name: "Latest Tour",OptionCode: "LatestTour",active: false,blocked: false,forbiddenFilterOptionCode: [],},{Name: "Oldest Tour",OptionCode: "OldestTour",active: false,blocked: false,forbiddenFilterOptionCode: [],},{Name: "Lowest Price",OptionCode: "LowestPrice",active: false,blocked: false,forbiddenFilterOptionCode: ["Free", "FreeAndPaid"],},],},]; setBlocked(filters, ["Free", "FreeAndPaid"]); console.log(filters);

 const filters = [ { FilterCode: "TourPrice", FilterName: "Tour Price", FilterIcon: null, Options: [ { Name: "Free", OptionCode: "Free", active: false, blocked: false, forbiddenFilterOptionCode: ["LowestPrice"], }, { Name: "Paid", OptionCode: "Paid", active: false, blocked: false, forbiddenFilterOptionCode: [], }, { Name: "Free and Paid", OptionCode: "FreeAndPaid", active: true, blocked: false, forbiddenFilterOptionCode: [], }, ], }, { FilterCode: "SortedBy", FilterName: "Sorted By", FilterIcon: null, Options: [ { Name: "Most Relevant", OptionCode: "MostRelevant", active: true, blocked: false, forbiddenFilterOptionCode: [], }, { Name: "Latest Tour", OptionCode: "LatestTour", active: false, blocked: false, forbiddenFilterOptionCode: [], }, { Name: "Oldest Tour", OptionCode: "OldestTour", active: false, blocked: false, forbiddenFilterOptionCode: [], }, { Name: "Lowest Price", OptionCode: "LowestPrice", active: false, blocked: false, forbiddenFilterOptionCode: ["Free", "FreeAndPaid"], }, ], }, ]; optionsToSearch = ["Free", "FreeAndPaid"]; const newFilters = filters.map((filter) => { const options = filter.Options.map((option) => { if (optionsToSearch.includes(option.OptionCode)) { return {...option, blocked: true }; } else { return option; } }); return {...filter, Options: options }; }); console.log(newFilters);

If you want to make a new array of objects, you can use .map() on your filters array, where you map each object a new object containing all the properties it original had (done using the spread syntax ... ), but overwrite the Options key with a newly mapped array. To map this array, you can build a new object from the take the properties/values from each option object (again using the spread syntax), and overwrite the blocked property based on whether the search array contains your OptionCode from the current option object:

 const filters = [{ FilterCode: "TourPrice", FilterName: "Tour Price", FilterIcon: 'show_Dollar', Options: [{ Name: "Free", OptionCode: "Free", active: false, blocked: false, forbiddenFilterOptionCode: ["LowestPrice"], }, { Name: "Paid", OptionCode: "Paid", active: false, blocked: false, forbiddenFilterOptionCode: [], }, { Name: "Free and Paid", OptionCode: "FreeAndPaid", active: true, blocked: false, forbiddenFilterOptionCode: [], }, ], }, { FilterCode: "SortedBy", FilterName: "Sorted By", FilterIcon: "show_Sort", Options: [{ Name: "Most Relevant", OptionCode: "MostRelevant", active: true, blocked: false, forbiddenFilterOptionCode: [], }, { Name: "Latest Tour", OptionCode: "LatestTour", active: false, blocked: false, forbiddenFilterOptionCode: [], }, { Name: "Oldest Tour", OptionCode: "OldestTour", active: false, blocked: false, forbiddenFilterOptionCode: [], }, { Name: "Lowest Price", OptionCode: "LowestPrice", active: false, blocked: false, forbiddenFilterOptionCode: ["Free", "FreeAndPaid"], }, ], } ]; const search = ["Free", "FreeAndPaid"]; const result = filters.map(obj => ({...obj, Options: obj.Options.map(option => ({...option, blocked: search.includes(option.OptionCode) })) })); console.log(result);

You could do this by mapping Options inside filters then checking tge search terms with includes :

const terms = ['Free']
const result = filters.map(f => {
  return {
    ...f
    Options: f.Options.map(o => {
      if (terms.includes(o.Name)) {
        return {
          ...o,
          blocked: true,
        }
       }
       return o
    })
  }
})
const getIndizesForPropValue = (propValue, list) => {
    return list
        .reduce((acc, curr, i) =>  [...acc, [i, curr.Options.findIndex((o) => o.OptionCode === propValue)]], [])
        .find((x) => x[1] >= 0)
};

const idx = getIndizesForPropValue('Free', filters);
filters[idx[0]].Options[idx[1]].OptionCode = 'NewValue'

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