Populating Javascript Array of Objects with an embedded Array of Objects - javascript

I am new to Javascript (familiar with C/C++) and I am trying to parse out an XML file and store it in an Array of Objects. The structure is similar to a bullet list where there is one main List item and possibly multiple List subitems:
var MenuLine =
[{
label : "null",
icon : "null",
Subitem:
[{
label : "null",
icon : "null"
}]
}];
Which allows me to use the following syntax:
var someRandomSubitemText = MenuLine[2].Subitem[4].label;
I tried populating this array using the .push method:
var tempMenuLine = [];
var tempSubitem = [];
$(xml).find("item").each(function()
{
tempMenuLine.label = $(xml).children("label").text();
tempMenuLine.icon = $(xml).children("icon").text();
$(this).children("subitem").each(function()
{
tempSubitem.label = $(this).children("label").text();
tempSubitem.icon = $(this).children("icon").text();
tempMenuLine.Subitem.push(tempSubitem);
});
MenuLine.push(tempMenuLine);
});
However this does not work since the .push method passes a reference to tempMenuLine and I am overwriting tempMenuLine with each iteration. Is there a way that I could write directly to the MenuLine array using something similar to the following syntax?
$(xml).find("item").each(function(index1)
{
MenuLine[index1].label = $(xml).children("label").text();
MenuLine[index1].icon = $(xml).children("icon").text();
$(this).children("subitem").each(function(index2)
{
MenuLine[index1].Subitem[index2].label = $(this).children("label").text();
MenuLine[index1].Subitem[index2].icon = $(this).children("icon").text();
});
});

Move your temp var declarations inside of your loops:
$(xml).find("item").each(function() {
var tempMenuLine = [];
tempMenuLine[0].label = $(xml).children("label").text();
tempMenuLine[0].icon = $(xml).children("icon").text();
tempMenuLine[0].Subitem = []
$(this).children("subitem").each(function(){
var tempSubitem = [];
tempSubitem[0].label = $(this).children("label").text();
tempSubitem[0].icon = $(this).children("icon").text();
tempMenuLine[0].Subitem.push(tempSubitem);
});
MenuLine.push(tempMenuLine);
});
This way, you're initializing a new item for each iteration of the loops, removing the "link" it had to the previous item.

A recursive solution just for fun.
var MenuLine = Xml2Array(xmlText, 'item');
function Xml2Array(xmlDocument, itemName) {
if (!$(itemName, xmlDocument).length) {
return;
}
var tmpArray = [];
$(itemName, xmlDocument).each(function() {
tmpArray.push({
label: $('label', this).first().text(),
icon: $('icon', this).first().text(),
Subitem: Xml2Array(this, 'subitem')
});
});
return tmpArray;
}

Related

problems filling an array with javascript

I parsed a json and I'm trying to take 2 values for each element from the json and put them in a array the problem is that I want to put the values into the array like a single element "array" example:
[
{ name: 'name1', elements: [ 'elem1' ] },
{ name: 'name2', elements: [ 'elem2', 'elem3' ] }
]
I tried 2 ways.
the first is this:
function getMonsters(json) {
var monsters = [];
var monster = {};
json.forEach(element => {
if (element.type === "large") {
monster['name'] = element.name;
monster['elements'] = element.elements;
monsters.push(monster);
}
});
return monsters;
}
the problem with the first way is that it always returns the same 2 values:
the second way is this:
function getMonsters(json) {
var monsters = [];
var monster = {};
json.forEach(element => {
if (element.type === "large") {
monsters.push(element.name, element.elements);
}
});
return monsters;
}
but the problem with the second way is that it returns each monster and element separately and not like in my example:
this is the json if u want to check : https://mhw-db.com/monsters
You are reusing the monster object every iteration in your first example. Either move the declaration of var monster = {} into the loop or, better yet, just push an object literal.
function getMonsters(json) {
const monsters = [];
json.forEach(({ elements, name, type }) => {
if (type === "large") {
monsters.push({ name, elements });
}
});
return monsters;
}
Your first attempt is almost correct. The reason why all of the items in the array end up being the same object is because monster is the same reference in all of the array items. You need a new instance of monster on every iteration. Just put your initialization of monster in your loop
function getMonsters(json) {
var monsters = [];
json.forEach(element => {
if (element.type === "large") {
var monster = {};
monster['name'] = element.name;
monster['elements'] = element.elements;
monsters.push(monster);
}
});
return monsters;

How can I add a key/value pair to a JavaScript object which is in an another object

I'm asking your help for the following code:
function vimeoImport() {
let videosToBeImported = [{
uri: "/videos/442638455",
name: "FOMME_1387_VD1",
modifed_time: "2020-07-29T09:24:48+00:00"
},{
uri: "/videos/442056086",
name: "FOMME_1387_VD2",
modifed_time: "2020-07-29T09:25:27+00:00"
},{
uri: "/videos/442638455",
name: "FOMME_2387_VD1",
modifed_time: "2020-07-29T09:24:48+00:00"
}];
let frtVideoUrlValues = {};
for (var index in videosToBeImported) {
var videos = videosToBeImported[index];
let videoName = videos.name;
let splitName = videoName.split('_');
let targetedVariationGroup = splitName[0].concat('_', splitName[1]);
let positionvideo = splitName[2];
let variationGroupParams = {};
variationGroupParams[positionvideo] = videos.uri;
if (targetedVariationGroup in frtVideoUrlValues) {
frtVideoUrlValues[targetedVariationGroup] += variationGroupParams;
} else {
frtVideoUrlValues[targetedVariationGroup] = variationGroupParams;
}
}
}
I tried to add a key/value pair (the key is a variable) in the targetedVariationGroup object which is in the frtVideoUrlValues object. When I try, I see the new key/value pair in the targetedVariationGroup but the merge is not functional and the 2 objects are not accessible:
And I try to obtain an object like this:
As, you didn't provide any output format, I am guessing the output should look like as follows(If this is not what you've wanted, pls provide proper output format):
{
FOMME_1387: [
{ VD1: '/videos/442638455' },
{ VD2: '/videos/442056086' }
],
FOMME_2387: [
{ VD1: '/videos/442638455' }
]
}
Now, to achieve this you should write code as follow:
function vimeoImport() {
let videosToBeImported = [
{
uri: "/videos/442638455",
name: "FOMME_1387_VD1",
modifed_time: "2020-07-29T09:24:48+00:00"
},
{
uri: "/videos/442056086",
name: "FOMME_1387_VD2",
modifed_time: "2020-07-29T09:25:27+00:00"
},
{
uri: "/videos/442638455",
name: "FOMME_2387_VD1",
modifed_time: "2020-07-29T09:24:48+00:00"
}
];
let frtVideoUrlValues = {};
for (var index in videosToBeImported) {
var videos = videosToBeImported[index];
let videoName = videos.name;
let splitName = videoName.split('_');
let targetedVariationGroup = splitName[0].concat('_', splitName[1]);
let positionvideo = splitName[2];
let variationGroupParams = {};
variationGroupParams[positionvideo] = videos.uri;
// here are the changes I've made
if(frtVideoUrlValues[targetedVariationGroup] === undefined) {
frtVideoUrlValues[targetedVariationGroup] = [];
}
frtVideoUrlValues[targetedVariationGroup].push(variationGroupParams);
}
console.log(frtVideoUrlValues);
}
vimeoImport();
The problem with your code is, you're using + to add object with another object, but + is only used to concat string in javascript. Instead of what you're doing, you should push objects into array. To add new elements in an array, you've to use push() method.
Also, notice, if key targetedVariationGroup in frtVideoUrlValues is undefined, I've assigned an empty array to targetedVariationGroup as follows:
frtVideoUrlValues[targetedVariationGroup] = [];
and then, pushed variationGroupParams object in the array as follows:
frtVideoUrlValues[targetedVariationGroup].push(variationGroupParams);

For..In Loop Overwriting ALL Array Values

I'm trying to use a for..in loop to iterate through a list of names, add them to a template object ('group'), then add each complete object to an array ('queryList'). This isn't working because each iteration is overwriting ALL values in the array. Any suggestions why this is happening?
// BATTERY OBJECT
var groupList = [ "LOGIN", "BROWSE", "SEARCH"];
// GROUP OBJECT
var group = {dbName: 'CARS', name: '', collectionName: 'group'};
// INIT VARS
var groupName = '',
queryList = [];
// COMPILATION FUNCTION
var buildGroupQueries = function(group){
// BUILD BATCH OF QUERIES
for (var i in groupList){
groupName = groupList[i];
group.name = groupName;
queryList[i] = group;
}
console.log(queryList);
}
buildGroupQueries(group);
It should look like:
[
{"dbName":"CARS","name":"LOGIN","collectionName":"group"},
{"dbName":"CARS","name":"BROWSE","collectionName":"group"},
{"dbName":"CARS","name":"SEARCH","collectionName":"group"}
]
Instead I'm getting:
[
{"dbName":"CARS","name":"SEARCH","collectionName":"group"},
{"dbName":"CARS","name":"SEARCH","collectionName":"group"},
{"dbName":"CARS","name":"SEARCH","collectionName":"group"}
]
You are creating an array of elements referring to the same object, so they all show the same name coinciding with the last time you changed it, which is "SEARCH" in your example.
You have to refer each element to a new object created from the one you want to use as a template.
To do so you can either loop over its properties or clone it as shown below:
// BATTERY OBJECT
var groupList = [ "LOGIN", "BROWSE", "SEARCH"];
// GROUP OBJECT
var group = {dbName: 'CARS', name: '', collectionName: 'group'};
// INIT VARS
var groupName = '',
queryList = [];
// COMPILATION FUNCTION
var buildGroupQueries = function(group){
var i, _group;
// BUILD BATCH OF QUERIES
for (i in groupList){
_group = JSON.parse(JSON.stringify(group));
groupName = groupList[i];
_group.name = groupName;
queryList[i] = _group;
}
console.log(queryList);
}
buildGroupQueries(group);
You modify the group object each time, but you need to modify its copy.
Add this code just after your line for (var i in groupList){
var _group = {};
for (var j in group){ _group[j] = group[j]; }
On each iteration you create a new object and copy to it all properties from the master object.

nesting multiple level of array with associative

data = [{'name':'John'},
{'name':'Smith'},
{'name':'James'}]
how to format the above array into this
var name = {
"user": {
"name" : [{'name':'John'},
{'name':'Smith'},
{'name':'James'}]
}
}
I tried var name['name'] = data and don't know how to wrap the result. I want to wrap the result with 'user' as it assoc.
You can't assign properties as you create the object. Either first create the object and then set the property:
var name = {};
name.user = { name : data };
or create the entire object at once:
var name = { user: { name: data } };
var data = [{'name':'John'},
{'name':'Smith'},
{'name':'James'}]
var name = {
"user": {
"name" : data
}
}

Best way to store this data (array, object, etc)

I need to store (many) objects or arrays of data, which need to have the following criteria:
I need to be able to add a new set of data into the existing data easily
I need to be able to sort the data by date/ time added easily (array in order of when entries were pushed to it)
I need to be able to grab an entry easily using a reference, either integer or string. This is important, at the moment I have to do an $.each() to loop through my data until I find the entry I want.
I have tried using a structure like:
saved_info = {
1001: {//all my data for ref 1001},
1002: {//all my data for ref 1002}
}
which gave me what wanted of being able to grab the info easily given a reference:
info = saved_info[1001];
however, the reference numbers I use aren't in order - I use a reference given to me (its a unique identifier), therefore the object isn't in order of when items were added/saved/pushed.
You can use two objects:
One that stores the data by key
Another that stores the sort order
This way you can (i) lookup an element by key (ii) loop over elements in the order they were inserted. Rough outline of the structure:
var DataObject = {
data: {},
sort: []
};
Here is how you add data to this structure:
DataObject.data[1004] = {name: "Test 4"};
DataObject.sort.push(1004);
DataObject.data[1001] = {name: "Test 1"};
DataObject.sort.push(1001);
DataObject.data[1003] = {name: "Test 3"};
DataObject.sort.push(1003);
DataObject.data[1002] = {name: "Test 2"};
DataObject.sort.push(1002);
Here is how you perform a random access:
console.log(DataObject.data[1001].name);
console.log(DataObject.data[1003].name);
And here is how you iterate over all elements in the order they were added:
var i;
for (i = 0; i < DataObject.sort.length; i++) {
console.log(DataObject.data[DataObject.sort[i]].name);
}
It is possible to wrap the entire logic inside a class:
function DataObject() {
this.data = {};
this.sort = [];
this.setItem = function (k, v) {
this.data[k] = v;
this.sort.push(k);
};
this.getItemByKey = function (k) {
return this.data[k];
};
this.getItemByPos = function (i) {
return this.data[this.sort[i]];
};
this.getAllItems = function () {
var i, r = [];
for (i = 0; i < this.sort.length; i++) {
r.push(this.data[this.sort[i]]);
}
return r;
};
}
var t = new DataObject();
t.setItem(1001, {name: "Test 1"});
t.setItem(1002, {name: "Test 2"});
t.setItem(1003, {name: "Test 3"});
t.setItem(1004, {name: "Test 4"});
console.log(t.getItemByKey(1001));
console.log(t.getItemByPos(0));
console.log(t.getAllItems());
Try to build a Json like this,
var xJson = {
"1001":{//all my data for ref 1001},
"1002":{//all my data for ref 1002}
};
and you can fetch the records as per your wish using the bracket notation, since we are using a numeric value as a key.
var xData = xJson["1001"];

Categories