Nested looping around an array - javascript

I am trying to loop all the values of an array and push that looped data into another array.
For example:
{
"cat": [
{
"view": [
{
"ent": [
{
"data": [
{}
],
"label": "abcd"
},
{
"data": [
{}
],
"label": "efgh"
}
]
}
]
}
]
I need to iterate until label and bring all the values of label into an array. This is what I have tried.
The issue is I am just getting the last value of label i.e. won in my array variable.
JS:
var ArrL = scope.res.cat;
var Array = [];
for(var i=0;i<ArrL.length;i++){
var ArrF = ArrL[i].view;
for(var j=0;j<ArrF.length;j++){
var ArrE = ArrF[j].ent;
for(var k=0;k<ArrE.length;k++){
var ArrLa = ArrE[k].label;
}
}
Array.push(ArrLa);
}
console.log(Array);
Expected output is ['joy','won'] but output after running the program is ['won'].

Since your Q is flagged as jquery, you can do this:
var cat = [
{
view: [
{
ent: [
{
data: [
{
key: "id",
value: "00"
},
{
key: "cid",
value: "123"
}
],
label: "joy"
},
{
key: "id",
value: "11"
},
{
key: "cid",
value: "234"
}
], // end ent
label: "won"
},
] //end view
}
];
var labels = [];
$.map( cat, function flattener( node ) {
if ( $.isPlainObject( node ) && node.hasOwnProperty('label') ) {
labels.push( node.label );
}
return ($.isArray( node ) || $.isPlainObject( node )) ? $.map( node, flattener) : node;
} );
console.log( labels );
Fiddle: http://jsfiddle.net/fFwQ6/
Thing to note is that order will be dictated by depth: deeper labels come last.
UPDATE:
It is easy to turn it into an utility function:
function grabKeys( source, keyName ) {
var values = [];
$.map( source, function flattener( node ) {
if ( $.isPlainObject( node ) && node.hasOwnProperty(keyName) ) {
values.push( node[keyName] );
}
return ($.isArray( node ) || $.isPlainObject( node )) ? $.map( node, flattener) : node;
} );
return values;
}
var labels = grabKeys( cat, 'label' );
var cids = grabKeys( cat, 'cid' );
UPDATE 2: Since 'cid' is a key value and not a name, we must use a slightly different method. Sorry I did not noticed it previously.
function grabPairedKeys( source, keyValue, keyName1, keyName2 ) {
keyName1 = keyName1 || 'key';
keyName2 = keyName2 || 'value';
var values = [];
$.map( source, function flattener( node ) {
if ( $.isPlainObject( node ) && node.hasOwnProperty(keyName1) && node.hasOwnProperty(keyName2) && node[keyName1] === keyValue ) {
values.push( node[keyName2] );
}
return ($.isArray( node ) || $.isPlainObject( node )) ? $.map( node, flattener) : node;
} );
return values;
}
var labels = grabKeys( cat, 'label' );
var cids = grabPairedKeys( cat, 'cid' );

You should use the push in the loop.
for(var i=0;i<ArrL.length;i++){
ArrF = ArrL[i].view;
for(var j=0;j<ArrF.length;j++){
ArrE = ArrF[j].ent;
for(var k=0;k<ArrE.length;k++){
ArrLa = ArrE[k].label;
Array.push(ArrLa);
}
}
}

Well, you only push the last value that was assigned to ArrLa after having iterated the view array. Instead, push the value right away when you encounter it:
var Array = [];
for(var i=0;i<ArrL.length;i++){
var ArrF = ArrL[i].view;
for(var j=0;j<ArrF.length;j++){
var ArrE = ArrF[j].ent;
for(var k=0;k<ArrE.length;k++){
Array.push(ArrE[k].label);
}
}
}
console.log(Array);

Related

how to array list to tree in javascript?

I have a list:
var list = ['parent-element', 'child-of-previus-element-1', 'child-of-previus-element-2'];
where each next element in the array is a child of the previous.
I want to transform this list into a tree structure, e.g.:
{
"parent-element": {
"childrens": [{
"child-of-previus-element-1": {
"childrens": [{
"child-of-previus-element-2": {
"childrens": []
}
}]
}
}]
}
}
I have tried:
var list = ['parent-element', 'child-of-previus-element-1', 'child-of-previus-element-2'];
var tree = {};
for (var i = 0; i < list.length; i++) {
if( list[i-1] && tree[list[i-1]] ){
tree[list[i-1]].childrens[list[i]] = {"childrens": []};
} else {
tree[list[i]] = {
"childrens": []
};
}
}
console.log( JSON.stringify(tree) );
but the output is:
{
"parent-element":{
"childrens":[]
},
"child-of-previus-element-2":{
"childrens":[]
}
}
You might reduce it right:
var list = ['parent-element', 'child-of-previus-element-1', 'child-of-previus-element-2'];
var tree = list.reduceRight((child, key) => ({ [key]: { children: [child] } }), null);
console.log(JSON.stringify(tree))

How to convert following Json object as a string like below

I have a json object as follows,
{
"category": "music",
"location": {
"city": "Braga"
},
"date": {
"start": {
"$gte": "2017-05-01T18:30:00.000Z"
},
"end": {
"$lt": "2017-05-12T18:30:00.000Z"
}
}
}
i need to create a query string as follows,
category=music | location.city = Braga | date.start.$gte = 2017-05-01T18:30:00.000Z | date.end.$lt = 2017-05-12T18:30:00.000Z
How can I achieve this?
This is what i have tried.
_.each(this.filter, (val: string, key: string) => {
if (key && val) {
filterArray.push(`${key}=${val}`);
}
});
You could iterate the keys and build a path to the value. Later join pathes and add value and join to the final string.
function getParts(object) {
function iter(o, p) {
Object.keys(o).forEach(function (k) {
if (o[k] && typeof o[k] === 'object') {
iter(o[k], p.concat(k));
return;
}
result.push(p.concat(k).join('.') + ' = ' + o[k]);
});
}
var result = [];
iter(object, []);
return result.join(' | ');
}
var object = { "category": "music", "location": { "city": "Braga" }, "date": { "start": { "$gte": "2017-05-01T18:30:00.000Z" }, "end": { "$lt": "2017-05-12T18:30:00.000Z" } } },
string = getParts(object);
console.log(string);
Sorry, I'm late, but still.
Method walk recursively runs through your JSON and calls callback function with chain of keys and value as arguments.
Then convert uses walk to translate JSON into your format:
var walk = function( data, iterator, stack ) {
var key;
stack = stack || [];
for ( key in data ) {
if ( typeof data[ key ] === 'string' ) {
iterator( stack.concat( [ key ] ), data[ key ] );
} else {
walk( data[ key ], iterator, stack.concat( [ key ] ) );
}
}
};
var convert = function( data ) {
var result = [];
walk( data, function( keys, value ) {
result.push( keys.join( '.' ) + ' = ' + value );
} );
return result.join( ' | ' );
};
var query_string = convert( /* your JSON here */ );

How to convert array of object into an array of object with different format?

I'm having an array of object,in which I'm storing the billkey and billvalue as attributes. I want billkey to be the key and billvalue to be the value of that particular key.
var log=[
{
billkey:"Name",
billvalue:"ABC"
},
{
billkey:"Department",
billvalue:"Computer"
}
{
billkey:"Name",
billvalue:"XYZ"
},
{
billkey:"Department",
billvalue:"Electrical"
}];
And I want to convert it into this format:
var log=[
{
Name:"ABC",
Department:"Computer"
},
{
Name:"XYZ",
Department:"Electrical"
}];
How about this simple solution. Hope it helps!
var log=[
{
billkey:"Name",
billvalue:"ABC"
},
{
billkey:"Department",
billvalue:"Computer"
},
{
billkey:"Name",
billvalue:"XYZ"
},
{
billkey:"Department",
billvalue:"Electrical"
}];
var arr = [];
var finalObj = [];
for(var i in log){
var someObject = log[i];
for(var j in someObject){
arr.push(someObject[j]);
}
}
for(var k = 0; k < arr.length; k+=4){
finalObj.push({
Name: arr[k+1],
Department: arr[k+3]
});
}
console.log(finalObj);
create the result using forloop
// store the values
var logs=[];
var log=[
{
billkey:"Name",
billvalue:"ABC"
},
{
billkey:"Department",
billvalue:"Computer"
},
{
billkey:"Name",
billvalue:"XYZ"
},
{
billkey:"Department",
billvalue:"Electrical"
},
];
loop the first array
for (i = 0; i < log.length; i++) {
// create empty variable for storing the values
var index = new Array();
// insert the first index value to key
index[log[i].billkey] = log[i].billvalue
// insert the second index value to key
index[log[i+1].billkey] = log[i+1].billvalue
// insert the result in to new array
logs.push(index);
// increment the i with 1
i=i+1;
}
console.log(logs);
You could use Array#reduce and use the remainder operator as witch for using either the last object or create a new one.
var log = [{ billkey: "Name", billvalue: "ABC" }, { billkey: "Department", billvalue: "Computer" }, { billkey: "Name", billvalue: "XYZ" }, { billkey: "Department", billvalue: "Electrical" }],
result = log.reduce(function (r, a, i) {
var o = {};
if (i % 2) {
r[r.length - 1][a.billkey] = a.billvalue;
} else {
o[a.billkey] = a.billvalue;
r.push(o);
};
return r;
}, []);
console.log(result);

Merging multiple arrays on shared keys in Javascript

I want to merge multiple arrays into one big array with shared keys.
What I've tried:
var conditions = [];
if( aa != undefined )
{
conditions.push( { "query" : { "must" : { "aa" : "this is aa" } } } );
}
if( bb != undefined )
{
conditions.push( { "query" : { "must" : { "bb" : "this is bb" } } } );
}
The above code is giving:
[
{
"query": {
"must": {
"aa": "this is aa"
}
}
},
{
"query": {
"must": {
"bb": "this is bb"
}
}
}
]
But I need this:
[
{
"query": {
"must": [
{
"aa": "this is aa"
},
{
"bb": "this is bb"
}
]
}
}
]
I am able to do it with PHP but I need to do it in native javascript or using underscore.js
Define the object your pushing - push everything to the inner array first - then push the object to the outer array:
var conditions = [];
var query = { query: {} };
if( aa != undefined ) {
if (!query["query"]["must"]) {
query["query"]["must"] = [];
}
//conditions.push( { "query" : { "must" : { "aa" : "this is aa" } } } );
query["query"]["must"].push({ "aa" : "this is aa" });
}
if( bb != undefined ) {
if (!query["query"]["must"]) {
query["query"]["must"] = [];
}
//conditions.push( { "query" : { "must" : { "bb" : "this is bb" } } } );
query["query"]["must"].push({ "bb" : "this is bb" });
}
conditions.push(query);
For each descendant of conditions, check if it exists, create it if it doesn't.
Then, finally, push your new object:
function addCondition(conditions, key, value) {
conditions[0] = conditions[0] || {};
conditions[0].query = conditions[0].query || {};
conditions[0].query.must = conditions[0].query.must || [];
var o = {};
o[key] = value;
conditions[0].query.must.push( o );
}
var conditions = [];
var aa = 1, bb = 1;
if (typeof(aa) !== 'undefined')
addCondition(conditions, "aa", "this is aa" );
if (typeof(bb) !== 'undefined')
addCondition(conditions, "bb", "this is bb" );
if (typeof(cc) !== 'undefined')
addCondition(conditions, "cc", "this is cc" );
document.getElementById('results').innerHTML = JSON.stringify(conditions, null, 2);
<pre id="results"></pre>
It's not quite trivial, because I see you want to make an array out of the last inner property.
Do those Objects you push into the conditions array already exist or are you defining them yourself?
You can solve your problem with a recursive function like this I believe:
EDIT: The code produces the exact result you wanted now.
var object1 = {
query: {
must: {
aa: "this is aa"
}
}
}
var object2 = {
query: {
must: {
bb: "this is bb"
}
}
}
var conditions = {};
function mergeObjects(object, parentObject){
for(var prop in object){
if(parentObject.hasOwnProperty(prop)){
if(typeof parentObject[prop] === "object" && shareProperties(parentObject[prop], object[prop])){
mergeObjects(object[prop], parentObject[prop])
}else{
parentObject[prop] = [parentObject[prop], object[prop]];
}
}else{
parentObject[prop] = object[prop];
}
}
}
function shareProperties(obj1, obj2){
for(var prop in obj1){
if(obj2.hasOwnProperty(prop)){
return true;
}
}
return false;
}
mergeObjects(object1, conditions);
mergeObjects(object2, conditions);
Output:
"{"query":{"must":[{"aa":"this is aa"},{"bb":"this is bb"}]}}"

How to remove duplicates from array that contains nested object

I have an array of nested object (I use this to populate my tree), something like below..
var obj1= {
text: "TreeRoot",
items: [ {
text: "subgroup1" ,
items: [ {
text: "subgroup2",
items: [ {
text: "subgroup3",
items: [ {
text: "subgroup4",
items: [ {
text: "subgroup5"
}]
}]
}]
}]
}]
};
var obj2 = {
text: "TreeRoot",
items: [ {
text: "subgroup1" ,
items: [ {
text: "subgroup2",
items: [ {
text: "subgroup3",
items: [ {
text: "subgroup4",
items: [ {
text: "subgroup5"
}]
}]
}]
}]
}]
};
var obj3= {
text: "TreeRoot",
items: [ {
text: "subgroup1" ,
items: [ {
text: "subgroup2"
}]
}]
}]
};
var finalArray=[];
finalArray.push(obj1);
finalArray.push(obj2);
finalArray.push(obj3);
Now I need to remove the duplicate objects from my final array using text(i.e I should remove obj2 from my array)...
This is what I tried..
var arr = {};
for ( var i=0; i < finalPath.length; i++ )
arr[finalArray[i]['text']] = finalArray[i];
finalArray= new Array();
for ( key in arr )
finalArray.push(arr[key]);
Can someone let me know the best possible way?
Edit:
I think the below solution works, but yet to test it completely...
var arr = {};
for ( var i=0; i < finalArray.length; i++ ){
if(finalArray[i].items){
for(var j=0;j<finalArray[i].items.length;j++){
arr[finalArray[i].items[j]['text']] = finalArray[i];
}
}else{
arr[finalArray[i]['text']] = finalArray[i];
}
}
finalArray= new Array();
for ( key in arr )
finalArray.push(arr[key])
Thanks,
Barani
JSON seems to be pretty simple to use, and keeps your code clean, but probably it will use a lot of processing.
There's another way to solve your problem, you can create a recursive function that will go through the array and compare each branch.
function areEqual(a, b) {
if( (a.items && !b.items) || (!a.items && b.items) ) return false;
else if(!a.items && !b.items) return a.text == b.text ? true : false;
else return (a.text == b.text) ? areEqual(a.items[0], b.items[0]) : false;
}
This code works with the data you've provided, but you will probably need to adjust the function if you want to test other values (not only text)
areEqual(obj1, obj2) : true
areEqual(obj1, obj3) : false
Edit:
Here is a simplified version of the function, and even better if you need to compare multiple elements (not only text)
function areEqual(a, b) {
var conditions = a.text == b.text /* && a.another_var == b.another_var */;
if( typeof(a.items) != typeof(b.items) ) return false;
if(a.items && b.items && conditions) return areEqual(a.items[0], b.items[0]);
return conditions;
}
Sorry but I think your code would fail if objects have a depth higher than 2.
At least, the logic seems quite strange.
Why don't you define a test to check if two objects are equal ? You can use a recursive test, or simply test the equality on a json version :
something like :
function are_equal(obj1,obj2) {
return JSON.stringify(obj1)==JSON.stringify(obj2);
}
and then use the response here Remove Duplicates from JavaScript Array :
uniqueArray = finalArray.filter(function(elem, pos) {
return are_equal(elem,pos);
})
I haven't tested it, hope this helps.
Try this code:
var ObjList = [......]; /*All your objects*/
var dict = {}; /*Dictionary for duplicate elimination*/
for (var obj in ObjList)
{
dict[JSON.stringify(obj)] = JSON.stringify(obj);
}
var newObjList = [];
for (var key in dict)
{
newObjList.push(key);
}
Now newObjList has all your unique items however deep the tree might be.

Categories