简体   繁体   中英

How to add a property to sub-objects with a certain parameter/value in JS?

I've got an object and i want to iterate through all of its subobjects/keys that hold the key-value pair 'pool: "luxury"'. Or in other words I want to iterate throu all rooms that are in the pool luxury to set a new parameter. What is a proper and efficient way to do that in js?

var rooms = {
    SU01: {
        enabled: true,
        pool: "comfort",
        ics_lnk : "https://avlblty.com/su01.ics",
        ics_txt : "",
    },
    SU02: {
        enabled: true,
        pool: "luxury",
        ics_lnk : "https://avlblty.com/su02.ics",
        ics_txt : "",
    },
    SU03: {
        enabled: true,
        pool: "luxury",
        ics_lnk : "https://avlblty.com/su03.ics",
        ics_txt : "",
    },
    SU11: {
        enabled: true,
        pool: "comfort",
        ics_lnk : "https://avlblty.com/su11.ics",
        ics_txt : "",
    },
    SU12: {
        enabled: true,
        pool: "luxury",
        ics_lnk : "https://avlblty.com/su12.ics",
        ics_txt : "",
    },
    ...

You can use Object.values() to get all the values in the object and filter to only keep the ones you want.

The code might look like this:

foreach (let room of Object.values(rooms).filter(r => r.pool == 'luxury')) {
    // Do something with room
}

Assuming this is your data set

const data = var rooms = {
    SU01: {
        enabled: true,
        pool: "comfort",
        ics_lnk : "https://avlblty.com/su01.ics",
        ics_txt : "",
    },
    SU02: {
        enabled: true,
        pool: "luxury",
        ics_lnk : "https://avlblty.com/su02.ics",
        ics_txt : "",
    },
    SU03: {
        enabled: true,
        pool: "luxury",
        ics_lnk : "https://avlblty.com/su03.ics",
        ics_txt : "",
    },
    SU11: {
        enabled: true,
        pool: "comfort",
        ics_lnk : "https://avlblty.com/su11.ics",
        ics_txt : "",
    },
    SU12: {
        enabled: true,
        pool: "luxury",
        ics_lnk : "https://avlblty.com/su12.ics",
        ics_txt : "",
    },
};

If the properties under the which the rooms are returned are important, we need to add those into the room objects, like this

const rooms = Object.keys(data).map(id => ({
  id,
  ...data[key],
}));

Otherwise, we can have all the rooms by simply calling

const rooms = Object.values(data);

Now that we have the rooms, we have to filter the get the ones with pool equals to luxury

const luxuryRooms = rooms.filter(room => room.pool === 'luxury');

Eventually you can add a new property with

const updatedRooms = luxuryRooms.map(room => ({
  ...room,
  newProperty: 'New Value',
}));

With lodash :

var _ = require('lodash')

_(rooms)
    .values()
    .filter(r => r.pool == poolName)
    .value()

Output:

[ { enabled: true,
    pool: 'luxury',
    ics_lnk: 'https://avlblty.com/su02.ics',
    ics_txt: '' },
  { enabled: true,
    pool: 'luxury',
    ics_lnk: 'https://avlblty.com/su03.ics',
    ics_txt: '' },
  { enabled: true,
    pool: 'luxury',
    ics_lnk: 'https://avlblty.com/su12.ics',
    ics_txt: '' } ]

Here's a solution that will work in most modern browsers. The result is a new object with a new property on the items from the input object matching your filter.

Instead of hardcoding the function to work with one filter I've made a function ( addPropToFiltered() ) that accepts parameters for the property/value you want to filter on, and parameters for adding a new value.

This mutates the original rooms object, but can also be easily changed to create a new object (and leave rooms as is).

The function works like this;

addPropToFiltered(inputObject, filterProp, filterValue, newProp, newPropValue);

For your particular question we would use this as:

addPropToFiltered(rooms, "pool", "luxury", "newProp", "New Value");

which would add a new property of newProp with a value of New Value to each room matching pool: "luxury" .

 const addPropToFiltered = function(rooms, prop, filter, newProp, newValue) { return Object.keys(rooms).reduce(function(result, id) { const room = rooms[id]; // Add new property if applicable if (room[prop] === filter) { room[newProp] = newValue; } result[id] = room; return result; }, {}) } const rooms = { SU01: { enabled: true, pool: "comfort", ics_lnk: "https://avlblty.com/su01.ics", ics_txt: "", }, SU02: { enabled: true, pool: "luxury", ics_lnk: "https://avlblty.com/su02.ics", ics_txt: "", }, SU03: { enabled: true, pool: "luxury", ics_lnk: "https://avlblty.com/su03.ics", ics_txt: "", }, SU11: { enabled: true, pool: "comfort", ics_lnk: "https://avlblty.com/su11.ics", ics_txt: "", }, SU12: { enabled: true, pool: "luxury", ics_lnk: "https://avlblty.com/su12.ics", ics_txt: "", } }; console.log(addPropToFiltered(rooms, "pool", "luxury", "newProp", "New Value")); console.log(rooms) 

The following code is ES2015 and clear in that it does not mutate any objects ( rooms is completely untouched):

 const addProperties = (rooms, pool, properties) => Object .keys(rooms) // take the keys "SU01", "SU02",... .filter(key => rooms[key].pool === pool) // take only keys with matching pool .reduce((newRooms, key) => ({ ...newRooms, [key]: { ...rooms[key], ...properties } // add properties to room }), rooms); // take "rooms" and update all changed rooms, which results in "newRooms" const rooms = { SU01: { enabled: true, pool: "comfort", ics_lnk : "https://avlblty.com/su01.ics", ics_txt : "", }, SU02: { enabled: true, pool: "luxury", ics_lnk : "https://avlblty.com/su02.ics", ics_txt : "", }, SU03: { enabled: true, pool: "luxury", ics_lnk : "https://avlblty.com/su03.ics", ics_txt : "", }, SU11: { enabled: true, pool: "comfort", ics_lnk : "https://avlblty.com/su11.ics", ics_txt : "", }, SU12: { enabled: true, pool: "luxury", ics_lnk : "https://avlblty.com/su12.ics", ics_txt : "", } }; const result = addProperties(rooms, "luxury", { newProperty: "new value" }); console.log(result); 

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