Javascript - Find multiple values in multidimensional array - javascript

Got some JSON that I need to go through to fetch some IDs.
The JSON looks like this:
var carousel = [
{
"acf": {
"content": [
{
"acf_fc_layout": "custom",
"content": "Some text"
},
{
"acf_fc_layout": "exhibition",
"exhibition": 2594
},
{
"acf_fc_layout": "exhibition",
"exhibition": 1234
}
]
},
}
]
For every content where acf_fc_layout == exhibition I must fetch the value (ID) of exhibition so it can be used to fetch further data. As you can see there's multiple exhibition IDs aswell.
My confusion here is that there are both object and array, and that they're nested. I've done some similar stuff with jQuery, but that's out of the question this time. Don't think I need IE8 support, but still find this tricky..

If your JSON simply looks as you say, this is a simple solution:
var i;
for (i = 0; i < carousel[0].acf.content.length; i++) {
if (carousel[0].acf.content[i].acf_fc_layout === "exhibition") {
// do something with carousel[0].acf.content[i].exhibition
}
}
Alternatively if you have much more content in your JSON, this might be relevant:
var i, j;
for (i = 0; i < carousel.length; i++) {
if (typeof carousel[i].acf != 'undefined' && typeof carousel[i].acf.content != 'undefined') {
for (j = 0; j < carousel[i].acf.content.length; j++) {
if (carousel[i].acf.content[j].acf_fc_layout === "exhibition") {
// do something with carousel[i].acf.content[j].exhibition
}
}
}
}

carousel[0].acf.content.forEach(function (item) {
if (item["acf_fc_layout"] === "exhibition") {
// do some stuff
// id for exhibition placed in item["exhibition"]
}
});

With your current structure, you need to use a foreach and check the value.
var carousel = [
{
"acf": {
"content": [
{
"acf_fc_layout": "custom",
"content": "Some text"
},
{
"acf_fc_layout": "exhibition",
"exhibition": 2594
},
{
"acf_fc_layout": "exhibition",
"exhibition": 1234
}
]
},
}
];
$.each(carousel[0].acf.content,function (i,v){
if(v.acf_fc_layout == "exhibition")
$(".result").append(v.exhibition+"<br>");
});
JSFIddle

http://jsfiddle.net/oucp3v5x/
$(carousel).each(function(i, el){
$(el.acf.content).each(function(i, el){
if(el.acf_fc_layout === 'exhibition') {
$('<div>', {
text: el.exhibition
}).appendTo($('#results'));
}
});
});
If acf have many content, you need to run additional loop and acf have to be array of objects.

Related

Is there a more efficient way to write a set of methods and functions modifying the same variable one after the other?

I have a series of items and reports which need to pull and modify sub-arrays from a lengthy JavaScript data file (which I can't modify). The sample below contains a snippet of an entry for demonstration-purposes assigned to the variable called data. I cannot in any way change the architecture of the data structure for data itself (in practice it is retrieved via a script tag src="[URL]" property), and other data beyond what is shown here does not appear to be 100% organized like a JSON file, if it makes a difference.
In the section below, I create a variable q5_yes which ultimately will hold a single array of values for the "Yes" responses from "Question_5" of a survey. To get it to the format I need though, I need to modify it in several steps.
While what I have below works on its own, I'm wondering if there's a better practice for combining these steps into a single one (and ideally makes it easier for re-use in the future as well since I'm going to be repeating this procedure a lot).
var data = {
"reSEQ": [{
"Entry_1": "Nov-2015",
"Question_5": [{
"Yes": 30
},
{
"No": 5
},
{
"Not Sure": 13
},
{
"Total": 48
}
],
"Question_6": [{
"Yes": 30
},
{
"No": 5
},
{
"Not Sure": 13
},
{
"Total": 48
}
]
}]
};
var q5_yes = data.reSEQ.map(function(e) {
return e.Question_5.map(function(e) {
return e.Yes;
});
});
var q5_yes = q5_yes.map(function(subarray) {
return subarray.filter(function(val) {
return val !== undefined;
});
});
var q5_yes = q5_yes.splice(0, q5_yes.length - 0);
var q5_yes = [].concat.apply([], q5_yes);
document.getElementById("foo").innerHTML = q5_yes;
<div id="foo">test</div>
EDIT: I do have a solution to answer my own question, which is to simply wrap the var q5_yes calls into a single function with parameters to make it re-usable. It doesn't reduce the bloat of this section of code, but makes it easy when repeating the process for other entries.
Example:
function getQuestion(question, answer){
var arrayCon = data.reSEQ.map(function(e) {
return e[question].map(function(e) {
return e[answer];
});
});
arrayCon = arrayCon.map(function(subarray) {
return subarray.filter(function(val) {
return val !== undefined;
});
});
arrayCon = arrayCon.splice(0, arrayCon.length - 2); //removes current & lifetime entries
arrayCon = [].concat.apply([], arrayCon);
return arrayCon
}
And then I just create a var and set it to the function e.g. var q5Value = getQuestion('Question_5', 'Yes')
Given the context of the problem, you can ensure that the mapping you want is located at the 0th index of each array, thus;
var data = {
"reSEQ": [{
"Entry_1": "Nov-2015",
"Question_5": [{
"Yes": 30
},
{
"No": 5
},
{
"Not Sure": 13
},
{
"Total": 48
}
],
"Question_6": [{
"Yes": 30
},
{
"No": 5
},
{
"Not Sure": 13
},
{
"Total": 48
}
]
}]
};
var q5_yes = data.reSEQ[0].Question_5[0].Yes;
document.getElementById("foo").innerHTML = q5_yes;
<div id="foo">test</div>
function getQuestion(question, answer){
var arrayCon = data.reSEQ.map(function(e) {
return e[question].map(function(e) {
return e[answer];
});
});
arrayCon = arrayCon.map(function(subarray) {
return subarray.filter(function(val) {
return val !== undefined;
});
});
arrayCon = arrayCon.splice(0, arrayCon.length - 2); //removes current & lifetime entries
arrayCon = [].concat.apply([], arrayCon);
return arrayCon
}
var q5Value = getQuestion('Question_5', 'Yes') // to get the desired vals as an array

better way to write the for loop

I want to loop through the array and check the condition using 'if' statement. If the condition is met then it should exit the for loop and execute other statements. after executing other statements, it should loop from next variable.
for ex. if I have a array named 'songs',
_(songs).forEach(function(song) {
if (song.genre == 1){
//do something and exit from for loop
}
});
// Do something else
Now I want to again loop through and start from where it left off earlier. I tried to achieve this like below:
var i = 0;
for(;i < songs.length; i++){
if(songs[i].genre == 3) {
//do something
i++;
break;
}
else if(songs[i].genre == 2) {
//do something
i++;
break;
}else{
//do something
i++;
break;
}
}
It serves the purpose. but is there anyway to make it efficient or better? Any suggestion would be helpful :)
function doStuffWithSongs(song) {
switch (song.genre) {
case 'pop':
// handle pop songs
break;
case 'rock':
// repeat for every genre
break;
}
};
songs.forEach(doStuffWithSongs);
You could also have doStuffWithSongs be a bunch of different functions and handle the switch in the forEach:
songs.forEach(song => {
switch (song.genre) {
case 'pop': return handlePopSongs(song);
case 'rock': return handleRockSongs(song);
// etc.
}
});
Have some objects to hold functions and songs
var songs = [{
"genre": "pop",
"name": "Hit me baby"
}, {
"genre": "rock",
"name": "Smoke on the water"
}],
handlers = {
pop: function(song) {
console.log("pop", song.name);
},
rock: function(song) {
console.log("rock", song.name);
}
}
for (var i = 0; i < songs.length; i++) {
handlers[songs[i].genre](songs[i]);
}
Unless for some reason your needing to keep order? You really should run a filter on the songs array creating a "genre" array, you could then simply loop through each array executing whichever function or actions you needed to take place.
//SONGS ARRAY
var songs = [
{
'name':'Work',
'genre': 0
},
{
name: 'Blessings',
genre: 1
},
{
name: 'Blame',
genre: 0
},
{
name: 'She Got It',
genre: 0
},
{
name: 'Controlla',
genre: 1
},
{
name: 'Get Low',
genre: 1
}
];
//FILTERED GENRE ARRAYS
var myRockSongs = songs.filter((o)=>(o.genre === 0) ? true : false);
var myPopSongs = songs.filter((o)=>(o.genre === 1) ? true : false);
//CONSOLE LOG
console.log(myRockSongs);
console.log(myPopSongs);

Filter by elements in an Array in AngularJS

I have a JSON File with Tasks. They are structured as follows:
[
{
"id":"1",
"name":"task1",
"tags":["tag1","tag2","tag3"]
},
{
"id":"2",
"name":"task2",
"tags":["tag4","tag2","tag5"]
},
{
"id":"3",
"name":"task3",
"tags":["tag3"]
}
]
Here's a Plunkr for what I want
http://plnkr.co/edit/kMhiHDyybHYxGfV7W39z?p=preview
Basically, this is what I want : http://jsfiddle.net/TahmidTanzim/N9Vqk/
I've looked through various SO questions and they all suggest I am doing it right.
However I don't understand where I am going wrong. I want only those tasks that contain the selectedTag to be displayed in the red list.
Thanks!
Just change filters to compare inner tags using arrays.
myapp.filter('tagFilter',function()
{
return function(Data,selectedTags)
{
if(selectedTags.length===0) return Data;
var tempData=[];
for(var i in Data) {
for(var z in Data[i].tags) {
for(var k in selectedTags) {
var value = selectedTags[k];
if(value == Data[i].tags[z]) {
tempData.push(Data[i]);
break;
}
}
}
}
return tempData;
}
});

Edit javascript array without reloading the page

I have a literal array that is loaded when the page loads... See below:
<script type="text/javascript">
var members = [
{
name:"Alan Lim",
id:"54700f06-a199-102c-8976-b1732b7ffc74",
positions:[
{
id:"4cdeb2a2-8897-102d-80ee-95364de284f0"
}
]
},
{
name:"Ben Sinclair",
id:"ed34b5a4-9b2f-102c-8475-9e610b13400a",
conflict:"true",
positions:[
{
id:"f00c2128-8895-102d-80ee-95364de284f0"
},
{
id:"f00c68ea-8895-102d-80ee-95364de284f0"
},
{
id:"4cde6824-8897-102d-80ee-95364de284f0"
},
{
id:"4cde9ea2-8897-102d-80ee-95364de284f0"
}
],
locations:[
{
id:"88fb5f94-aaa6-102c-a4fa-1f05bca0eec6"
},
{
id:"930555b0-a251-102c-a245-1559817ce81a"
}
]
},
{
name:"Debbie Wright",
id:"fa49307a-9cfb-102d-bd08-842c500d506d"
}
]
</script>
Is there anyway to edit the array without reloading the page? For example, I want to add conflict:"true" to Alan Lim...
E.g:
Change this:
{
name:"Alan Lim",
id:"54700f06-a199-102c-8976-b1732b7ffc74",
positions:[
{
id:"4cdeb2a2-8897-102d-80ee-95364de284f0"
}
]
},
To this:
{
name:"Alan Lim",
id:"54700f06-a199-102c-8976-b1732b7ffc74",
conflict:"true",
positions:[
{
id:"4cdeb2a2-8897-102d-80ee-95364de284f0"
}
]
},
Trust that makes sense :) The reason for this is because I use other JavaScript to pull information from this array. When I make a change with the other JavaScript I want to add and subtract to this array to reflect the changes...
You can loop through to find the member you want (by name it seems given the question) then edit it, like this:
for(var i=0; i<members.length; i++) {
if(members[i].name == "Alan Lim")
members[i].conflict = "true";
}
You can give it a try here, or make it a bit more generic like this:
function setProp(name, prop, value) {
for(var i=0; i<members.length; i++) {
if(members[i].name == name)
members[i][prop] = value;
}
}
Since your array is numerically indexed, Can you not just do:
members[0]['conflict'] = "true";

Convert JSON to HTML Tree

I would like to generate an HTML tree (preferably UL-LI) from the JSON example below. Does anyone have a simple, recursive JS function (not a framework) that can handle this specific structure? Thanks for your help!
{ "folder" : [ {
"title" : "1",
"folder" : [ {
"title" : "1.1",
"folder" : [ {
"title" : "1.1.1",
} , {
"title" : "1.1.2",
} ]
} ]
} , {
"title" : "2",
} ] }
function to_ul (obj) {
// --------v create an <ul> element
var f, li, ul = document.createElement ("ul");
// --v loop through its children
for (f = 0; f < obj.folder.length; f++) {
li = document.createElement ("li");
li.appendChild (document.createTextNode (obj.folder[f].title));
// if the child has a 'folder' prop on its own, call me again
if (obj.folder[f].folder) {
li.appendChild (to_ul (obj.folder[f].folder));
}
ul.appendChild (li);
}
return ul;
}
Caveat: No error checking! If a 'title' or 'folder' is missing, the whole thing could blow up.
I had a problem getting my browser to accept the data structure submitted by the OP, but here is a fully working example I've drawn up for my own, similar purposes. Beside the function I provide the data structure as well, with name/branches instead of title/folder.
function to_ul(branches) {
var ul = document.createElement("ul");
for (var i = 0, n = branches.length; i < n; i++) {
var branch = branches[i];
var li = document.createElement("li");
var text = document.createTextNode(branch.name);
li.appendChild(text);
if (branch.branches) {
li.appendChild(to_ul(branch.branches));
}
ul.appendChild(li);
}
return ul;
}
function renderTree() {
var treeEl = document.getElementById("tree");
var treeObj = {
"root": [{
"name": "George & Sarah Trede",
"branches": [{
"name": "George & Frances Trede",
"branches": [{
"name": "Mary (Trede) Jempty"
}, {
"name": "Carol (Trede) Moeller"
}]
}, {
"name": "Mary (Trede) Sheehan"
}, {
"name": "Ward Trede"
}]
}]
};
treeEl.appendChild(to_ul(treeObj.root));
}
renderTree()
<div id="tree"></div>
I've used PURE with some success in the past for this kind of thing.
function to_li(obj, name) {
var li = document.createElement("li");
if (typeof(name) != "undefined") {
var strong = document.createElement("strong");
strong.appendChild(document.createTextNode(name + ": "));
li.appendChild(strong);
}
if (typeof(obj) != "object"){
li.appendChild(document.createTextNode(obj));
} else {
var ul = document.createElement ("ul");
for (var prop in obj){
ul.appendChild(to_li(obj[prop],prop));
}
li.appendChild(ul);
}
return li;
}
Check out the jquery plugin JSON2HTML, it's a little simpler to use than PURE and I've used it on a couple of site's I've created.
http://json2html.com
#Boldewyn: I believe you can also use a For...In loop instead of a regular For loop to shorten the code a bit. Of course, I don't have much experience using this kind of loop, so please check my code snippet.
for (var i in obj.folder) {
li = document.createElement ("li");
li.appendChild (document.createTextNode (i.title));
// if the child has a 'folder' prop on its own, call me again
if (i.folder) {
li.appendChild (to_ul (i.folder));
}
}
I have made a pip package for the same do check it out JSON2tree. Install it using pip install json2tree then use cli tool to create HTML tree.
json2tree -j example.json -o output.html

Categories

Resources