0

I have a JS object, that looks almost like this:

let usrData = {
  admin_0_id: "123",
  admin_0_role: "abc",

  admin_1_id: "123",
  admin_1_role: "abc",

  admin_2_id: "123",
  admin_2_role: "abc",

  admin_3_id: "123",
  admin_3_role: "abc",

  admin_4_id: "123",
  admin_4_role: "abc"
}

Now I want to access them like this.

let i;
for (i = 0; i < 5; i++) {
//look at the following line.
    console.log("Admin ID: " + usrData.admin_ + i + _id + ", Role: " + usrData.admin_ + i + _role);
}

The console.log() line is invalid for sure. but is there any way to do make it work in such a way?

Note: I can't rearrange or change the usrData JS object.

Thank you! Have a great day.

ulou
  • 5,542
  • 5
  • 37
  • 47
  • 1
    Would there be `admin_5_id` ? – ikhvjs Jul 27 '21 at 12:28
  • Form strings, like `"admin_" + i + "_id"`, then use the `[ ]` operator to access the properties. Better, re-arrange your data structure as an array of objects with properties "admin_id" and "admin_role". – Pointy Jul 27 '21 at 12:29
  • 3
    Please be aware is not JSON. That is a JS object – evolutionxbox Jul 27 '21 at 12:29
  • 2
    Does this answer your question? [JavaScript property access: dot notation vs. brackets?](https://stackoverflow.com/questions/4968406/javascript-property-access-dot-notation-vs-brackets) – Alon Eitan Jul 27 '21 at 12:30

5 Answers5

1

While I would not recommend to access JS objects like this as you would loose a lot of type checking, but yes it is possible to access the elements like so :

let i;
for(i=0; i<5; i++) {
  //look at the following line.
  console.log("Admin ID: "+ usrData["admin_" + i + "_id"] + ", Role: "+ usrData["admin_" + i + "_role"]);
}
tsamridh86
  • 1,480
  • 11
  • 23
1

You can access property in at least two ways:

  • userData.something
  • userData['something']

and the result will be the same.

Solution (please notice I used , in console.log instead of +, cause + might print unexpected things in some cases):

const usrData = {
  admin_0_id: "0123",
  admin_0_role: "0abc",

  admin_1_id: "1123",
  admin_1_role: "1abc",

  admin_2_id: "2123",
  admin_2_role: "2abc",

  admin_3_id: "3123",
  admin_3_role: "3abc",

  admin_4_id: "4123",
  admin_4_role: "4abc"
}


for(let i=0; i < 5; i++) {
  //look at the following line.
  console.log(
      "Admin ID: ", usrData[`admin_${i}_id`],
      "Role: ", usrData[`admin_${i}_role`]
  );
}
ulou
  • 5,542
  • 5
  • 37
  • 47
1

I would recommend storing the length of the keys and access it dynamically as the object may contain more than 5 items in the future.

let usrData = {
  admin_0_id: "0",
  admin_0_role: "a",

  admin_1_id: "1",
  admin_1_role: "b",

  admin_2_id: "2",
  admin_2_role: "c",

  admin_3_id: "3",
  admin_3_role: "d",

  admin_4_id: "4",
  admin_4_role: "e",
};

const keysLength = Object.keys(usrData).length / 2;

for (let i = 0; i < keysLength; i++) {
  console.log(
    `Admin ID: ${usrData[`admin_${i}_id`]} Role: ${usrData[`admin_${i}_role`]}`
  );
}
ikhvjs
  • 5,316
  • 2
  • 13
  • 36
0

You could reduce your object into an array of objects where each prop is grouped by an index. This way, if you need to use the data in any other way, the objects can be treated as actual objects.

let usrData = {
  admin_0_id: "123", admin_0_role: "abc",
  admin_1_id: "234", admin_1_role: "def",
  admin_2_id: "345", admin_2_role: "ghi",
  admin_3_id: "456", admin_3_role: "jkl",
  admin_4_id: "567", admin_4_role: "mno"
};

const items = Object.entries(usrData)
  .reduce((acc, [key, value]) => {
    const [match, index, prop] = key.match(/^\w+_(\d+)_(\w+)$/);
    acc[+index] = {
      ...(acc[+index] || {}), // Can use '??' instead of '||'
      [prop]: value
    };
    return acc;
  }, []);

items.forEach(({ id, role }) => console.log(`Admin ID: ${id}, Role: ${role}`));
.as-console-wrapper { top: 0; max-height: 100% !important; }
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
0

Others have demonstrated how you can use dynamic object keys. But another possibility is to restructure that object on the fly to be more useful in other work. This may be entirely irrelevant to you, but I find it useful to convert objects in formats like this into more useful ones when doing my work with them.

So if we had a magic restructure function, we could be working instead on data that looks like:

{
  "admin": [
    {
      "id": "123",
      "role": "abc"
    },
    {
      "id": "123",
      "role": "abc"
    },
    {
      "id": "123",
      "role": "abc"
    },
    {
      "id": "123",
      "role": "abc"
    },
    {
      "id": "123",
      "role": "abc"
    }
  ]
}

which is much easier to work with. (updatedData.admin.forEach (...), for instance.)

But it turns out not too hard to build our restructure on top of two helpers I use regularly:

const setPath = ([p, ...ps]) => (v) => (o) =>
  p == undefined ? v : Object .assign (
    Array .isArray (o) || Number .isInteger (p) ? [] : {},
    {...o, [p]: setPath (ps) (v) ((o || {}) [p])}
  )

const hydrate = (xs) =>
  xs .reduce ((a, [p, v]) => setPath (p) (v) (a), {})

const restructure = (o) => 
  hydrate (
    Object .entries (o) 
      .map (([k, v]) => [
        k .split ('_') .map ((p) => /^\d+$/ .test (p) ? Number(p) : p), 
        v
      ])
  )

let usrData = {
  admin_0_id: "123",
  admin_0_role: "abc",

  admin_1_id: "123",
  admin_1_role: "abc",

  admin_2_id: "123",
  admin_2_role: "abc",

  admin_3_id: "123",
  admin_3_role: "abc",

  admin_4_id: "123",
  admin_4_role: "abc"
}

console .log (restructure (usrData))
.as-console-wrapper {max-height: 100% !important; top: 0}

Here, setPath takes a path such as ['admin', 2, 'role'], and a value such as 'abc' and an object and returns a copy of that object, setting the value at that path, creating any intermediate nodes as needed. hydrate takes an array of path-value pairs and creates a brand new object as needed.

Our restructure function then splits the keys of an object on _, converts any nodes containing only digits to numbers and then passes these new path arrays (alongside the corresponding values) to hydrate to create a more fully-realized object described by your flat structure and its _-joined keys.

As I said, this might not meet any of your requirements. But it also might, and it's a useful way to look at the problem.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103