0

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 : "",
    },
    ...
5
  • What is the new property you want to set on the filtered set? Commented Jul 16, 2017 at 11:27
  • Its some more or less complex merging of time periods which will result in a new object that will be stored in each room. named "merged_ics" Commented Jul 16, 2017 at 12:21
  • Do you want to create a new object, or update this one? Commented Jul 17, 2017 at 7:36
  • @torazaburo: update this one Commented Jul 17, 2017 at 14:52
  • @haemse - i've updated my solution to update the rooms object. Commented Jul 18, 2017 at 21:39

5 Answers 5

1

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: '' } ]
Sign up to request clarification or add additional context in comments.

1 Comment

This only filters the objects matching the string. It does not add a new property to the objects as it asks in the question.
1

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
}

3 Comments

This only filters the objects matching the string. It does not add a new property to the objects as it asks in the question.
At this point yes. I didn't know about Object.values though. I've changed it now. Thanks again!
The current node.js version does not support Obejct.entries()
1

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',
}));

1 Comment

This only filters the objects matching the string. It does not add a new property to the objects as it asks in the question.
1

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)

Comments

0

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);

Comments

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.