0

I have following sample code:

var x = [
{input1: "aaa"},
{input2: "bbb"},
{input444: "ddd"},
{input55: "eee"}
{input3: "ccc"},
]

I am trying to get values of props which if exists in the object something like

x.forEach((item, index) => {
 console.log(item.[`input${index}`]);
})

So for above sample code : I want output to be ["aaa", "bbb", "ccc"]

I know the first part of the property (which in this example is 'input') and second part will be index only

Is it possible to know the values using Optional chaining? What I am missing?

Mandeep Singh
  • 1,287
  • 14
  • 34
  • Could you elaborate more please. Which values are you interested in getting – Rilla Apr 14 '21 at 13:35
  • 1
    The initial object shows bad practice. You should never need properties to be constructed like . If you need values in a sequence, then use a flat array. – trincot Apr 14 '21 at 13:38
  • actually they are attribute of html tags which will come like this – Mandeep Singh Apr 14 '21 at 13:41
  • 1
    It is also bad practice to give such pattern to HTML attributes. – trincot Apr 14 '21 at 13:41
  • What if the order of the objects in `x` is different and `input3` comes before `input1`? – trincot Apr 14 '21 at 13:42
  • Yes, it can happen, order is not defined @trincot, agreed but it is legacy code and can u share some pointer how to give attribute names in a loop? – Mandeep Singh Apr 14 '21 at 13:47
  • instead of having to guess what the property names are you could use an array like `[{name: "input1", value: "aaa"}, {name: "input2", value: "bbb"}...]` – James Apr 14 '21 at 13:59
  • You already accepted an answer, but there are still things to clarify, and the accepted answer assumes the order is defined :S. What if there is `input9` or `input11` or `input21`. When are you no longer interested in those? What if there is a `input5`, but no `input4`? Would you want an array with a gap? – trincot Apr 14 '21 at 14:01
  • yeah, you are right, as order is not defined, this answer will not work for it – Mandeep Singh Apr 14 '21 at 14:10
  • Can you answer the other open questions? – trincot Apr 14 '21 at 14:12
  • yea, I am not interested in any other prop, only the one which will matches the string+index – Mandeep Singh Apr 14 '21 at 14:14
  • What is the maximum suffix value that you consider correct? Like `input5` is OK, but `input6` is not? What if there is no `input1`, but there is `input2`? Should the resulting array have an undefined entry in its first slot? .... – trincot Apr 14 '21 at 14:18

3 Answers3

1

You need just to add one to index and take bracket notation for the object without dot.

The optional chaining operator ?. works only for having undefined source value. It does not switch some program logic for either showing a value or not. In this case, you could check if the property exists in the object and then show th wanted part without some optional chaining

var x = [{ input1: "aaa" }, { input2: "bbb" }, { input3: "ccc" }, { input444: "ddd" }, { input55: "eee" }];

x.forEach((item, index) => {
    if (`input${index + 1}` in item)
        console.log(item[`input${index + 1}`]);
});
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

Optional chaining makes little sense unless you are only looking for a specific property. Use Object.values or Object.entries.

var x = [
  {input1: "aaa"},
  {input2: "bbb"},
  {input3: "ccc"},
  {input4: "ddd"},
  {input5: "eee"}
]

x.forEach((item, index) => {
 console.log(Object.values(item));
 console.log(Object.values(item)[0]); // If it is just one, reference it
})

If it has to match only if the index matches than it still does not require optional chaining to read the value.

var x = [
  {input1: "aaa"},
  {input2: "bbb"},
  {input3: "ccc"},
  {input4: "ddd"},
  {input555: "eee"}
]

x.forEach((item, index) => {
 console.log(item[`input${index+1}`]);
})

And after your 5th or so edit, to get the output you want is even weirder.... You would need to use reduce OR map and filter. You need to keep track of the current index.

const x = [
  {input1: "aaa"},
  {input2: "bbb"},
  {input444: "ddd"},
  {input55: "eee"},
  {input3: "ccc"},
];


let current = 1;
const out = x.reduce(function (acc, obj) {
  const key = `input${current}`;
  if(obj.hasOwnProperty(key)){
    acc.push(obj[key]);
    current++;
  }
  return acc;
}, []);

console.log(out);
epascarello
  • 204,599
  • 20
  • 195
  • 236
0

Since the order of the input is not guaranteed, I would do this:

var x = [{input1: "aaa"}, {input2: "bbb"},{input444: "ddd"},{input55: "eee"},{input3: "ccc"},];

let result = Object.assign([], ...x.flatMap(o => 
    Object.entries(o).filter(([k]) => 
        k.startsWith('input') && +k.slice(5) >= 1 && +k.slice(5) <= x.length
    ).map(([k, v]) => 
        ({ [k.slice(5)-1]: v })
    )
));
    
console.log(result);

Some characteristics of this solution:

  • Requires that the suffix in the property name lies between 1 and the length of the input array.
  • Allows that some objects in the input array have no properties that match the pattern inputXX, while others may have multiple such properties.
  • A value that is assigned to a property inputN will be stored at index N-1 in the resulting array, even if that means there will be gaps in the array.
trincot
  • 317,000
  • 35
  • 244
  • 286