• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

javascript - looping through variables to create new dynamic variables

LEGEND ,
Jun 06, 2022 Jun 06, 2022

Copy link to clipboard

Copied

Anyone got an ideas?

 

I have a list of dogs as separate variables, coming from a badly formated API.  Should have put the dogs in an array!

 

dog1 = "Poodle";

dog2 = "Greyhound";

dog3 = "Beagle";

dog4 = "Border Terrier";

dog5 = "Blood Hound";

dog6 = "West Highland Terrier";

dog7 = "Alsatian";

dog8 = "Scooby Doo";

etc...

 

Anyway I want to 'loop' through the dogs:

 

for(let i = 0; i < 20; i++) {

listDogs.innerHTML += `${dog[i]}`;

}

 

Obviously the above doesnt work as its not valid code but you get the idea.

 

I can get this working using 'eval' but am reluctant to use it because of poor write ups.

 

for(let i = 0; i < 20; i++) {

let dogList = eval(`dog${i}`);
listDogs.innerHTML += `<li>${dogList}</li>`

}

 

or I can push to an array, which I can then loop through, but is kind of long-winded and not very elegant, but more secure:

 

let dogList = [];

dogList.push(dog1);

dogList.push(dog2);

dogList.push(dog3);

dogList.push(dog4);

dogList.push(dog5);

dogList.push(dog6);

etc...

 

 

Is there some other solution that I'm obviously missing which creates dynamic variables like eval does (it obviously bolts a string and a variable number together to form a new variable)???

 

Cheers

 

Os

 

 

Views

460

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 2 Correct answers

Community Expert , Jun 07, 2022 Jun 07, 2022

did you try the Function() alternative as

 

dog1 = "Poodle";
dog2 = "Greyhound";
dog3 = "Beagle";
dog4 = "Border Terrier";
dog5 = "Blood Hound";
dog6 = "West Highland Terrier";
dog7 = "Alsatian";
dog8 = "Scooby Doo";
let dogs = [];
for (let i=1; i<9; i++){
    let value = Function('return dog'+i)()
    dogs.push(value)
}
console.log(dogs)

Votes

Translate

Translate
Community Expert , Jun 09, 2022 Jun 09, 2022
        let dogs = []
        let result = {
            "dogShow": [
                {
                    "showId": "Number",
                    "showName": "String",
                    "showCategory": "String",
                    "showLocation": "String",
                    "showDetails": "String",
                    "showDog1": "String",
                    "showDog2": "String",
                    "showDog3": "String",
                    "showDog4": "String",
                    "show
...

Votes

Translate

Translate
LEGEND ,
Jun 06, 2022 Jun 06, 2022

Copy link to clipboard

Copied

Hey there,

This is missing a lot of critical bits of information and not very clear 😞


Where is the content actually coming from?

You mention API.. What is the output, is it JSON or... What is tha actual data you have to work with - this is crticial.

There should be zero reason to use eval or most of what your looking to do as it does not make much sense in if your pulling data and rendering it on a web page.

Happy to help but could you provide a bit more informaiton.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 07, 2022 Jun 07, 2022

Copy link to clipboard

Copied

Not much more info l can add, it is json but instead of using an array to send back the list of dogs, whoever produced the file is sending the list of dogs back as separate strings -

dog1: "string",

dog2: "string",

dog3: "string"

etc

which I can easily access but was looking  for a more elegant way of looping through the separate strings in one operation.

 

Using eval is not ideal but l can use an expression to clean the string if that helps and pushing each dog to an array and looping through the array works but is bloated and ugly. 

 

Just thought there might be an alternative solution which works like eval where a dynamic variable is produced in a loop - dog +1, dog + 2, etc which can access the separate string information

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 07, 2022 Jun 07, 2022

Copy link to clipboard

Copied

did you try the Function() alternative as

 

dog1 = "Poodle";
dog2 = "Greyhound";
dog3 = "Beagle";
dog4 = "Border Terrier";
dog5 = "Blood Hound";
dog6 = "West Highland Terrier";
dog7 = "Alsatian";
dog8 = "Scooby Doo";
let dogs = [];
for (let i=1; i<9; i++){
    let value = Function('return dog'+i)()
    dogs.push(value)
}
console.log(dogs)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 07, 2022 Jun 07, 2022

Copy link to clipboard

Copied

you took the wind out of my sails...

although the sails do not belong to me 😉

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 07, 2022 Jun 07, 2022

Copy link to clipboard

Copied

quote

did you try the Function() alternative as

 

By @L e n a

 

 

Yes, that's what I was looking or hoping for. That's much cleaner and more elegant solution indeed. I've never come across that Function() solution before despite searching for a few hours on Google for a better way to achieve what I wanted. Is it documented anywhere?

 

Now I just have to combine it into my real code but can't see any reason why it should not work.

 

Thanks

 

Os

 

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 07, 2022 Jun 07, 2022

Copy link to clipboard

Copied

I'm glad that this can feed your needs.

Well, as you can see, it's better than eval(), but it is not fully secure.

Anyway it just execute in the global scope... so you can still use a third function to filter your expectation throught arguments

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 07, 2022 Jun 07, 2022

Copy link to clipboard

Copied

OK, thanks for that link. I'm none the wiser when reading the developer.mozilla.org website BUT it works so that's all that matters to me, I'll leave the jargon to those with more of a technical mindset. Its one to keep in the toolbox though.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 07, 2022 Jun 07, 2022

Copy link to clipboard

Copied

OK I have a scoping issue, I think!

 

I'm getting the details of the dog show from an onclick event link which passes the dog show 'id' to a function:

 

function dogShowFunc(id) {
const dogShow = returnedData.find(function(showId) {
return showId.id === id;
});

 

So now ALL the information of that dog show is included in an array 'dogShow'.

 

I'm now trying to find the right code combination to pass the array to the Function. Can it even be passed to the function? I'm getting 'dogShow' is not defined: (tried several different variation but not finding the right one)


for (let i=1; i<9; i++){
let value = Function(`return ${dogShow.dog}` + i)()
console.log(value)
dogList.push(value)
}
console.log(dogList);

}

// end of function

 

If I use:

`return ${dogShow.dog} + ${i}` or `return ${dogShow.dog + i}`

I get some return - NaN multiple times

 

If I use:

`return ${dogShow.dog}` + i

I get - undefined1 is not defined

 

I'm running out of combinations?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 07, 2022 Jun 07, 2022

Copy link to clipboard

Copied

I ended up stumbing upon another solution after many, many attempts:

 

I created variables in a variables array then used those variables when looping through the 'dogShow' array which contained all the information about the dog show.

 

${dogShow[variable]} and it worked a treat.

 

let variables = [];

for (let i = 1; i < 20; i++) {
variables[i] = "dog"+ i;
}
variables.forEach(function(variable) {
if(dogShow[variable] === '') {
return;
}
else {
dogList.innerHTML += `
<li>${dogShow[variable]}</li>
`
}
})

 

 

Never give up, I guess. There seems to be a solution when all looks lost if you stick at it!!

 

I dont know what these things are called in an array so I called them 'variables' or just bits of info which become  identifiers in the context I used them:

 

let variables = [dog1 , dog2 , dog3 , dog4]

 

dogShow[variable] which becomes:

dogShow.dog1 , dogShow.dog2 etc

 

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 07, 2022 Jun 07, 2022

Copy link to clipboard

Copied

I see where your going and the data is as you pointed out very annoyingly not friendly.

I do think the above is still over the top.

 

Firstly I go with the data.

The Data is not good so it needs to be better. They are all Dogs so you only need the data inside the quotation marks.

 

var match = myString.match(/"([^"]*)"/);

 

Something like this will just leave you with all use cases that match the regex. This is basically getting all content inside any "".

Since there is multiple this returns you an array of items.

match[0] would be Poodle.
Then you just loop through them.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 08, 2022 Jun 08, 2022

Copy link to clipboard

Copied

You're right l was over thinking the problem and found yet another way using the square bracket notation rather than the dot notation, which keeps everything a lot simpler. I guess what threw me was the structure of the json file, where it would have been cleaner to include the dog categories in a nested array rather than single entries.

 

However l have learned something from all the replies so it's been positive if time consuming, so thanks to everyone who responded with suggestions of a solution, its been a great help.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 08, 2022 Jun 08, 2022

Copy link to clipboard

Copied

OK, that is a new bit of information.

You said JSON.

If data above is what is there it is NOT JSON.
If you have a JSON file or string your reading from it would be valid and that is a whole different thing. You have specific Javascript you would parse the JSON and render, this also is way less code then the above solutions as well.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 09, 2022 Jun 09, 2022

Copy link to clipboard

Copied

quote

OK, that is a new bit of information.

You said JSON.

If data above is what is there it is NOT JSON.


By @Liam Dilley

 

Not sure what it is then, the API claims its json, looks like json to me. I get the data back the same way as I've always retrieved json data from an API.

 

Seems I was just over complicating the issue. The key was to use the bracket notation instead of the dot notation, nothing more required.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 09, 2022 Jun 09, 2022

Copy link to clipboard

Copied

just in case, copy pâste a snippet of what the API send you back...

we will see if it's plain text, pure javascript, or json... 🙂

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 09, 2022 Jun 09, 2022

Copy link to clipboard

Copied

Below is the basic file structure. There's a lot more data  (I've cut a lot out) but you can see the format:

 

{

"dogShow": [
{
"showId": "Number",
"showName": “String”,
"showCategory": "String",
"showLocation": “String”,
"showDetails": “String”,

"showDog1": “String",
"showDog2": “String",
"showDog3": “String",
"showDog4": “String",
"showDog5": “String",
"showDog6": “String",
"showDog7": “String",
"showDog8": “String",
"showDog9": “String",
"showDog10": "String",

}
]

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 09, 2022 Jun 09, 2022

Copy link to clipboard

Copied

        let dogs = []
        let result = {
            "dogShow": [
                {
                    "showId": "Number",
                    "showName": "String",
                    "showCategory": "String",
                    "showLocation": "String",
                    "showDetails": "String",
                    "showDog1": "String",
                    "showDog2": "String",
                    "showDog3": "String",
                    "showDog4": "String",
                    "showDog5": "String",
                    "showDog6": "String",
                    "showDog7": "String",
                    "showDog8": "String",
                    "showDog9": "String",
                    "showDog10": "String",
                }
            ]
        }
        Object.entries(result.dogShow[0]).forEach(([key, value]) => {
           if ( key.startsWith("showDog") ) dogs.push( value );   
        })
        console.log(dogs)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 09, 2022 Jun 09, 2022

Copy link to clipboard

Copied

and if you need the index... replace the expression by this one

 

dogs[ Number(key.substring(7)) ] = value

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 09, 2022 Jun 09, 2022

Copy link to clipboard

Copied

Not tested your offering BUT as usual there is probably 101 ways to achieve exactly the same outcome:

 

Once I had retreived the dogShow {} object by filtering the main results I just looped through it using bracket notation:

 

for (let i = 1; i < 20; i++) {

if(dogShow[`showDog${i}`] === '' || dogShow[`showDog${i}`] === null) {
dogList.innerHTML += '';
}
else {
dogList.innerHTML += `
<li>${dogShow[`showDog${i}`]}</li>

`

}
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 09, 2022 Jun 09, 2022

Copy link to clipboard

Copied

Birnou, that works. I could output the value where its needed without pushing the value to an array and then having to loop through that:

 

Object.entries(dogShow).forEach(([key, value]) => {
if(key.startsWith("showDog") && value)
dogList.innerHTML += `<li>${value}</li>`;
});

 

Never seen 'Object.entries' or 'key.startsWith' being used in any video I've watch and that's been a lot over the years.

 

Anyways from struggling to get the information initially now it seems there are  numerous ways lol - I always said web-development is a 'loose cannon', that is what makes it so much harder to learn, because every one has their own way!

 

Its another tool in the box I need to remember is available. Thanks.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 09, 2022 Jun 09, 2022

Copy link to clipboard

Copied

cool that you like it, you're right so many ways for handling the same issue...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 09, 2022 Jun 09, 2022

Copy link to clipboard

Copied

LATEST

one of the reads that I really like is Speaking Javascript by Axel Raushmayer... well many other authors are very interesting like Zakas, Stefanov, Osmani, Crockford... and many others, but Raushmayer is particulary meticulous

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines