0

I'm trying to get the a variable from a list with a concatenation of the path, but it doesn't work.

Here is the list. I want the name in people.Tutor and the abbrev in base.Module:

let parameters = {
  people: {
    Tutor: [{
      "id": 226,
      "name": "."
    }]
  },
  base: {
    Module: [{
      id: 1,
      abbrev: 'AMN'
    }]
  }
}

Here I try to concatenate the path (I made a for loop where I search for the type, it can be people.Tutor or base.Module):

let type_concat = "parameters." + type;
type_concat.replace(/"/g,"");

Finally here I try to find the names in people.Tutor or the abbrev in base.Module and add them into a list:

type_concat.find(function(n) { 
  if (n.id === constraints[l].parameters[k].id_list[m]) {
    tab_username.push(n.name)
  }
});

Here is the result in console :

type_concat.find is not a function

Barmar
  • 741,623
  • 53
  • 500
  • 612
WAWABC
  • 5
  • 3
  • why don't you parse the JSON and use the object? You should not try to parse a JsON by yourself with string commands – Thallius Jun 17 '21 at 15:28
  • `replace()` returns a new string, it doens't modify the string in place. And `find()` is used on arrays, not strings. – Barmar Jun 17 '21 at 15:29
  • 1
    It's not clear why you're trying to do it in this manner when you can simply iterate through `parameters.people.Tutor` or `parameters.base.Module`...? – Rory McCrossan Jun 17 '21 at 15:29
  • 2
    @ClausBönnhoff I don't see any JSON or any relation to it. –  Jun 17 '21 at 15:29
  • Is type a string path to the nested array like `type = "base.Module"` or `"people.Tutor"`? You probably need `const array = type.split(".").reduce((a,p) => a[p], parameters)`. – adiga Jun 17 '21 at 15:33
  • [Convert JavaScript string in dot notation into an object reference](https://stackoverflow.com/questions/6393943) – adiga Jun 17 '21 at 15:37
  • Rory McCrossan, it's only 2 exemples, there are many more and i don't want to do on iterate for each one . – WAWABC Jun 17 '21 at 15:46
  • I want to find elements in parameters.type but type is a string. – WAWABC Jun 17 '21 at 15:47
  • Barmar, i tried to concat the path by using this: ```let type_concat = "parameters." + type; type_concat.replace(/"/g,"");``` – WAWABC Jun 17 '21 at 15:48
  • i want as a result parameters.people.Tutor, then parameters.base.Module, then parameters.something.somewhat. – WAWABC Jun 17 '21 at 15:49
  • As adiga mentions, [Convert JavaScript string in dot notation into an object reference](https://stackoverflow.com/questions/6393943/convert-javascript-string-in-dot-notation-into-an-object-reference) should help you. But hopefully what's most helpful is the advice in the accepted answer: "novices who find their way to this answer must ask themselves the question 'why am I doing this?'" – pwilcox Jun 17 '21 at 15:51
  • pwilcox, I am trying to use it rn but i don't know how i can apply it here – WAWABC Jun 17 '21 at 15:53
  • I see your problem applying it. I retracted my close vote because this is highly related but has one difference. I'll post an answer soon if someone doesn't beat me to it. – pwilcox Jun 17 '21 at 16:00
  • Ok thank you guys for your help – WAWABC Jun 17 '21 at 16:07
  • You can close it as a duplicate of [Convert JavaScript string in dot notation into an object reference](https://stackoverflow.com/questions/6393943) – adiga Jun 17 '21 at 16:55

2 Answers2

0

I prefer the Lodash way and it's already a default dependency in most of my projects. Don't reinvent the wheel. Lodash provides utility functions, like get, to access elements by path:

let parameters = {
  people: {
    Tutor: [{
      "id": 226,
      "name": "."
    }]
  },
  base: {
    Module: [{
      id: 1,
      abbrev: 'AMN'
    }]
  }
}

console.log(_.get(parameters, 'people.Tutor').map(tutor => tutor.name));
console.log(_.get(parameters, 'people.Tutor.0'));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
0

Your question is highly related to this one. Basically, you want to take a string representing a path to a nested object property and then get the value as though the string were code.

Ninjagecko's solution is to use the following logic.

'a.b.etc'.split('.').reduce((o,i)=>o[i], obj);

Your question here though has an added problem in that one of your properties is an array of objects, and you want to be able to traverse through the array. But for you, you can't immediately use it without error:

'base.Module[0]abbrev'.split('.').reduce((o,i)=>o[i], obj);
// produces an error because of an undefined reference

However, because of the nature of the logic, you CAN do:

'base.Module.0.abbrev'.split('.').reduce((o,i)=>o[i], obj);

Here it is in action:

let parameters = {
  people: { Tutor: [{ "id": 226, "name": "." }]},
  base: { Module: [{ id: 1, abbrev: 'AMN' }] }
}

function stringGetter (getter) { 
  return getter
    .split('.')
    .reduce((o,i)=>o[i], parameters);
}

console.log(stringGetter("people.Tutor.0.name"));
console.log(stringGetter("base.Module.0.abbrev"));

But please heed ninjagecko's warning:

novices who find their way to this answer must ask themselves the question "why am I doing this?"

His warning is actually quite detailed and so may help you determine if your use-case is appropriate or not. Give it a read.

pwilcox
  • 5,542
  • 1
  • 19
  • 31