Javascript length of array in object - javascript

I have a Javascript object defined as follows:
var active = {
waypoints: [],
scenario: []
}
I push to array scenario with:
var myScenario = {
id: terrainId,
text: text
};
active.scenario.push(myScenario);
However I get 0 when:
console.log(active.scenario.length);
So of course I cannot loop through the array content. If I do:
console.log(active.scenario)
I see the array content within Chrome plus the correct array length. I have similar code that defines and works with arrays, but outside of an object definition.
Most grateful for insight into why length is 0.

It works fine:
JSFiddle
var terrainId = 1;
var text = "text";
var active = {
waypoints: [],
scenario: []
}
var myScenario = {
id: terrainId,
text: text
};
active.scenario.push(myScenario);
console.log(active.scenario.length);
Looks like the problem is somewhere else.

Related

Is it efficient to create multiple keys pointing to the same object?

I have an array of countries, where each country have three properties.
const countries = [
{ name: "Poland", alpha: "POL", code: "616" },
{ name: "Hungary", alpha: "HUN", code: "348" },
// and so on...
]
Later on I want to easily access each country by any of these properties.
I was thinking of reducing this array to an object that would have three keys for each country pointing to the very same country object.
Something like this:
const countriesObject = countries.reduce((object, country) => {
const { name, alpha, code } = country;
// Create individual country object
object[name] = { ...country };
// Reference just created country object
object[code] = object[name];
object[alpha] = object[name];
return object;
});
In the end I could access each country object either by its name, code or alpha.
countriesObject["Poland"] // →
countriesObject["POL"] // → The same object
countriesObject["616"] // →
My question is, would it be considered good practice, or there are some better ways to achieve the same or similar result?
Thank you!
That's fine, as all of those keys, as you correctly noted, will be pointing to the same object. The biggest problem that I see here is that it's easy to reduce readability of the code by using this approach. Let's say we have this fragment:
console.log( countriesObject[id] );
The question is, what is id here? Is it full country name? or just alpha? or code? You might just not care, true, but if you do, consider giving them additional structure:
const countriesObject = countries.reduce((object, country) => {
const { name, alpha, code } = country;
const countryCopy = { ...country };
// it makes sense to place them on the same line to show the intent
object.name[name] = object.code[code] = object.alpha[alpha] = countryCopy;
return object;
}, { name: {}, code: {}, alpha: {} });
Another potential issue is that you won't be able to drop the countries easily from this object; it's not enough to delete just a single key pointing to it, you'll have to go and remove all three. But that doesn't seem to be a big thing here; this looks more like a dictionary.
You can indeed write it like this:
var countries = {[
"poland": {
alpha: "POL", code: "616"
},
"hungary": {
alpha: "HUN", code: "348"
}
]}
Accessing each country like this:
var poland = countries.poland;
This, in turn, produces more readable code:
var alpha = countries.poland.alpha;
instead of
var alpha = countries[0].alpha;
But there is no set preference.
Docs

Select Random Item (shown in pairs) from Array & Remove It, Restart Once Array is Empty

I'm super newbie in coding and I need help to achieve this code.
I'm trying to get a random item (in pairs) from an array and then remove it from this array until user gets to the last item or 60 days have gone from using the service (cookie?)... I have build a script with the help of other questions here in stackoverflow and here is my results so far.
`<script>
var randomizer = document.getElementById("getImgBut");
var dog1 = '/app/wp-content/mediaApp/yo-creo-mi-realidad/01F.jpg';
var dog2 = '/app/wp-content/mediaApp/yo-creo-mi-realidad/01B.jpg';
var dogpics=[dog1,dog2];
var yourPics = [
dogpics,
[ '/app/wp-content/mediaApp/yo-creo-mi-realidad/02F.jpg', '/app/wp-content/mediaApp/yo-creo-mi-realidad/02B.jpg' ],
[ '/app/wp-content/mediaApp/yo-creo-mi-realidad/03F.jpg', '/app/wp-content/mediaApp/yo-creo-mi-realidad/03B.jpg' ],
[ '/app/wp-content/mediaApp/yo-creo-mi-realidad/04F.jpg', '/app/wp-content/mediaApp/yo-creo-mi-realidad/04B.jpg' ],
[ '/app/wp-content/mediaApp/yo-creo-mi-realidad/05F.jpg', '/app/wp-content/mediaApp/yo-creo-mi-realidad/05B.jpg' ],
[ '/app/wp-content/mediaApp/yo-creo-mi-realidad/06F.jpg', '/app/wp-content/mediaApp/yo-creo-mi-realidad/06B.jpg' ] //This array has 52 cards but I cutted it for example purposes
];
function get_random_number(array){
return Math.floor(Math.random() * array.length |0);
} // here is where I have tried to modify with other scripts like the one in this page https://stackoverflow.com/questions/38882487/select-random-item-from-array-remove-it-restart-once-array-is-empty with no success
randomizer.addEventListener("click", function() {
var rand_number = get_random_number(yourPics);
console.log(rand_number);
document.getElementById('img1').src = yourPics[rand_number][0];
document.getElementById('img2').src = yourPics[rand_number][1];
});
var card = document.querySelector('.card');
card.addEventListener( 'click', function() {
card.classList.toggle('is-flipped');
});
</script>`
Thank you for your help!
I don't fully understand what you mean by "remove in pairs", but I'll answer presuming you mean you wish to remove the image ending in 02F.jpg at the same time as removing the image ending in 02B.jpg, and then 03F.jpg at the same time as 03B.jpg.
The solution to this that I will propose is that we will structure your data a bit differently to begin with. That is, if those images, the "B image" and "F image" are linked, we could keep them in the same `javascript object. This would look like:
var yourPics = [
{
bImage: '/app/wp-content/mediaApp/yo-creo-mi-realidad/02F.jpg',
fImage: '/app/wp-content/mediaApp/yo-creo-mi-realidad/02B.jpg'
},
{
bImage: '/app/wp-content/mediaApp/yo-creo-mi-realidad/03F.jpg',
fImage: '/app/wp-content/mediaApp/yo-creo-mi-realidad/03B.jpg'
}...]
This would then be an array of objects, rather than strings. We can access the bImage property of an object with just
myObject = yourPics[0]
myObject.bImage
We could delete one of those objects those at random via splice.
myRandomlyRemovedObject = yourPics.splice(myIndexToDeleteFrom, 1) would remove 1 object from yourPics at position of myIndexToDeleteFrom, which you presumably would choose randomly. myRandomlyRemovedObject would be assigned to the one object we removed.
I think this object based approach is safer since you will know for a fact that you will removed both matching strings at the same time.

How would I go about using a multidimensional array variable in javascript

Hi there before I start I did try looking through the search about writing variables so if this has been asked and answered then I do apologise but this is baffling me ....
So here goes ..
example of what I am talking about
var i = e[ab]
var n = e[cd][ef]
var t = e[cd][gh]
I know that when I want var i I can put e.ab but how would I go about writing var n and var t
So assuming your object looks like this (based on your description, it sounds like you want to access an object which is the property of another object), and you want to access them through the indexer properties (which would be a property of a property).
var e = {
ab : "variableOne",
cd : {ef:"ef object"},
gh : {ij:"ij object"},
}
var i = e["ab"]
//if these are properties, then you need to add quotes around them
//to access a property through the indexer, you need a string.
var n = e["cd"]["ef"]
var t = e["gh"]["ij"]
console.log(i);
console.log(n);
console.log(t);
console.log("this does the same thing:")
console.log(e.ab);
console.log(e.cd.ef);
console.log(e.gh.if);
In your example the object would look like
//e is the parameter, but I show it as a variable to show
// it's relation to the object in this example.
e = {
now_playing: {artist:"Bob Seger"; track:"Turn the Page"}}
}
this is different than an array of arrays:
var arr = [
['foo','charlie'],
['yip', 'steve'],
['what', 'bob', 'jane'],
];
console.log(arr[0][0]); //foo
console.log(arr[0][1]); //charlie
console.log(arr[1][0]); //yip
console.log(arr[1][1]); //steve
console.log(arr[2][2]); //jane
https://jsfiddle.net/joo9wfxt/2/
EDIT:
Based on the JSON provided, it looks like parameter e in the function is assigned the value of the item in the array. With your code:
this line will display: "Rock you like a hurricane - Nontas Tzivenis"
$(".song_title .current_show span").html(e.title);
and this line will display: "Rascal Flatts - Life is a Highway".
$(".song_title .current_song span").html(e.np);
If it's not displaying you might want to double check your JQuery selectors. This ".song_title .current_song span" is selecting it by the classes on the element.
I think you are in need of a bit of a refresher on basic JavaScript syntax. Here's how you can assign an "empty object" to a variable, then start to assign values to it's properties:
e = {}
e.ab = {}
e.cd = {}
e.cd.ef = "data"
or you can use the associative array syntax for property access:
e = {}
e["ab"] = {}
e["cd"] = {}
e["cd"]["ef"] = "data"
You see the latter is using the object e like a two-deep associative array. Is that what you are looking to do?
JavaScript is not strongly typed. So an Array "a" could contain objects of different types inside.
var a = [ "a value", [1, 2, 3], function(){ return 5 + 2;}];
var result = a[0]; //get the first item in my array: "a value"
var resultOfIndexedProperty = a[1][0]; //Get the first item of the second item: 1
var resultOfFunc = a[2](); //store the result of the function that is the third item of my array: 7
Hope this helps a little.

How to access elements inside nested objects in a Javascript loop using variable names?

I'm clueless. I have a JSON string like this which I need to check for a supplied "property" (postsome in the following example):
var index_file =
[{
"indexAB":[
{ "postsome": ["keyword_abc", "keyword_def"] },
{ "testsome": ["keyword_111", "keyword_222"] }
]
},{
"index_random": [
{ "postsome": ["keyword_abc"] }
]
}]
There my be any number of indices ("indexAB", "index_random") with n objects inside.
I need to "find" my property postsome but I cannot get it to work, because I'm struggling with the correct way of accessing the object.
So:
for (var i = 0, l = indices.length; i < l; i += 1) {
doc._id = "postsome",
index_name = "indexAB";
indices[i]["indexAB"]; // ok, returns object on correct iteration
indices[i][index_name]; // undefined
indices[i].indexAB[0][doc._id] // ok, returns undefined or keywords
indices[i][index_name][0][doc._id] // undefined
}
Question:
How can I access a nested object in loop using a variable name index_name?
This is not a direct answer to your question but I believe that it may actually help you more than giving you a complicated way to access values in your object.
If instead of this JSON object:
var index_file =
[{
"indexAB":[
{ "postsome": ["keyword_abc", "keyword_def"] },
{ "testsome": ["keyword_111", "keyword_222"] }
]
},{
"index_random": [
{ "postsome": ["keyword_abc"] }
]
}];
you would have this much simpler data structure:
var index_file =
{
"indexAB": {
"postsome": ["keyword_abc", "keyword_def"],
"testsome": ["keyword_111", "keyword_222"]
},
"index_random": {
"postsome": ["keyword_abc"]
}
};
then it would be much easier to access, using just:
var value = index_file.indexAB.postsome[0]; // no loops, no nothing
// value == "keyword_abc"
See: DEMO
I think that what you should change is your data model because currently it is something that is very far from the idea of JSON and it will always be very hard do access data in it.
A couple of issues
"indexAB" only exists on the first element in the array
you cannot have dots inside variable names.
I suggest you test whether indexAB is a property of the object before deferencing it further. See example below:
Fixed
var indices = index_file;
for (var i = 0, l = indices.length; i < l; i++) {
var doc_id = "postsome";
var index_name = "indexAB";
indices[i]["indexAB"]; // ok, returns object on correct iteration
indices[i][index_name]; // undefined
if ("indexAB" in indices[i]) {
indices[i].indexAB[0][doc_id] // ok, returns undefined or keywords
indices[i][index_name][0][doc_id] // undefined
}
}
index_name is undefined because the line prior to that raises an error
doc._id = "postname" // this causes an error
Just use a simple string
doc = "postname"

Using concatenation and a passed parameter to loop through an array

var Animals = {
"Europe": { "weasel.jpg": "squeak", "cow.jpg": "moo"},
"Africa": { "lion.jpg": "roar", "gazelle.jpg": "bark"},
};
function region(a){
var b = "Animals."+a;
for(var index in b) {
var target = document.getElementById('div1');
var newnode = document.createElement('img');
newnode.src = index;
target.appendChild(newnode)
}
}
RELEVANT HTML
<li onclick="europe('Europe')">Europe</li>
Goal: on the click of the Europe <li>, pass the word Europe into my region function where it is then concatenated to produce Animals.Europe
This is in order to identify an array within the object structure at the top using the for(var index in Animals.Europe) loop. Why is the concatenation which produces Animals.Europe not treated in the same way as if I had typed this out?
In addition, you can see that I have used arrays to store an image source and description for different animals. Using my limited coding knowledge this was all I could think of. Is there an easier way to store image/description data in order to produce in HTML?
"Animals." + a is just a string value, e.g. "Animals.Europe", which is not the same thing as Animals.Europe. If you change the first line to var b = Animals[a];, you should be all set.
Edit: and as elclanrs pointed out, it should be region('Europe'), not europe('Europe').
Why is the concatenation which produces Animals.Europe not treated in the same way as if i had typed this out?
In this case the variable b is just a string ("Animals.Europe"), which is treated like any other string (i.e. a list of characters). This means that when you attempt to loop through it (for(index in b)) you will be looping over a simple list of characters.
What you can do instead is use the square brace notation of accessing an objects properties. This means you can instead write var b = Animals[a], retrieving attribute a from Animals. You can read more about working with objects in this way on this MDN page
You can access the europe property using the following
Animals[a]
Also you're calling a "europe" function when you should be calling "region"
You're not storing animals in arrays here, but in objects with the image names as keys. Usually you'll want to use relevant names as keys. For example if you want arrays of animals for each continent
var Animals = {
"Europe": [{
imageSrc: "weasel.jpg",
cry: "squeak"
},{
imageSrc: "cow.jpg",
cry: "moo"
}],
"Africa": [{
imageSrc: "lion.jpg",
cry: "roar"
},{
imageSrc: "gazelle.jpg",
cry: "bark"
}]
};
Now Animals['Europe'] gives an array of objects, where you could eventually store other properties. So if b is an array your loop will now look like:
var b = Animals['Europe'];
for(var i=0; i < b.length; i++) {
var target = document.getElementById('div1');
var newnode = document.createElement('img');
var animalData = b[i]; // The array item is now an object
newnode.src = animalData.imageSrc;
target.appendChild(newnode)
}

Categories