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);
Related
(React web app development)
In order to check if the current stock status of products, I use ID of products to loop through json data.
I am trying to retrieve value of "DATAPAYLOAD" by key (id) from json (below). idsent is string passed from another component. But "if (Data.response[i].id === idsent)" this condition always appears to be false because I got "failed" in console.
That would be really helpful if someone could take a look at the following code and give me some sujections, thanks in advance!
onButtonClicked = () => {
const idsent="D56F36C6038DFC8244F"
for (var i = 0; i < Data.response.length; i++) {
if (Data.response[i].id === idsent) {
name = Data.response[i].DATAPAYLOAD;
const word = '<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>';
if (name.includes(word)) {
return true;
}
else {
return false;
}
}
console.log("failed");
}
The following is part of the json data that is requested through fetch get-method.
Data= {
"code": 200,
"response": [
{
"id": "CED62C6F96BD0E21655142F",
"DATAPAYLOAD": "<AVAILABILITY>\n <CODE>200</CODE>\n
<INSTOCKVALUE>OUTOFSTOCK</INSTOCKVALUE>\n</AVAILABILITY>"
},
{
"id": "D56F36C6038DFC8244F",
"DATAPAYLOAD": "<AVAILABILITY>\n <CODE>200</CODE>\n
<INSTOCKVALUE>LESSTHAN10</INSTOCKVALUE>\n</AVAILABILITY>"
},
{
"id": "4536C9E608B563A749",
"DATAPAYLOAD": "<AVAILABILITY>\n <CODE>200</CODE>\n
<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>\n</AVAILABILITY>"
},
{
"id": "3A576872130625CABFADEE68",
"DATAPAYLOAD": "<AVAILABILITY>\n <CODE>200</CODE>\n
<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>\n</AVAILABILITY>"
}
]
}
Thank you again.
You probably wanted console.log("failed"); outside of the for loop like the following (so that it only executes once all the data is processed):
onButtonClicked = () => {
const idsent="D56F36C6038DFC8244F"
for (var i = 0; i < Data.response.length; i++) {
if (Data.response[i].id === idsent) {
name = Data.response[i].DATAPAYLOAD;
const word = '<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>';
if (name.includes(word)) {
return true;
}
else {
return false;
}
}
}
console.log("failed");
When the fetch is successful, You need to read and parse the data using json(). Pleas read this
onButtonClicked = async () => {
const idsent="D56F36C6038DFC8244F"
Data = await Data.json(); // json() will create a promise
for (var i = 0; i < Data.response.length; i++) {
if (Data.response[i].id === idsent) {
name = Data.response[i].DATAPAYLOAD;
const word = '<INSTOCKVALUE>INSTOCK</INSTOCKVALUE>';
if (name.includes(word)) {
return true;
}
else {
return false;
}
}
console.log("failed");
}
The reason you get failed, is because the first time through, the ID does not match the one sent, so it console logs the "failed" message. Then the second time through the for loop it matches the data, and then hits the next if, which checks for the value. Since the value you are searching for is included in the data, it returns true and the for loop is exited. The reason you see the fail log is because you are logging when the id doesn't match and there are 3 records in that array where the id don't match, the first one being one of them.
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
I have an array with a list of customers. I am declaring a function that takes a customer name as a parameter. I want this function to loop through the array to find out whether or not the customer is in the array.
var customers = [
{fullName: 'Marshall Hathers',
dob: '01/07/1970'},
{fullName: 'Margaret May',
dob: '01/07/1980'}
];
The function:
function findCustomer(customer) {
for(i=0; i<customers.length; i++) {
var found;
if(customer === customers[i].fullName) {
found = true;
console.log('Customer has been found');
break;
} else {
found = false;
console.log('Customer has not been found');
break;
}
}
It works well the first time a customer is found, but it prints out incorrectly when trying to find the second customer.
Can anyone please assist?
So look at what you're actually saying in your loop. The loop body will run for each customer. So you're saying
For the first customer in the array
if this is my customer
print "found" and stop looping
otherwise
print "not found" and stop looping
Does that look right to you? Does looking at the first record alone really tell you that the customer isn't found?
And note that since all possibilities end with "and stop looping" the 2nd record is never examined. The whole point of a loop is that in at least some condition, you don't stop looping, right? So that you would then see the step repeated for the 2nd, and so on...
Omit the else part and break the for loop if found.
function findCustomer(customer) {
var found, i;
for (i = 0; i < customers.length; i++) {
if (customer === customers[i].fullName) {
found = true;
console.log('Customer has been found');
break;
}
}
if (!found) {
console.log('Customer has not been found');
}
}
Use the Array.some prototype function to find the element
function findCustomer(customer) {
var found = customers.some(function(item) {return item.fullName == customer;});
console.log(found ? 'Customer has been found': 'Customer has not been found');
}
You are exiting the loop when your script reach to a break
So if you look for the second customer, you will enter in the "else". And there you have got a break that exit from the loop, so you will never get the console.log
Just remove the break; statement from the else block;
Here I rewritten the function for you.
function findCustomer(customer) {
var found = false;
for(i=0; i<customers.length; i++) {
if(customer === customers[i].fullName) {
found = true;
break;
} else {
found = false;
}
}
if(found){
console.log('Customer has been found');
}else{
console.log('Customer has not been found');
}
}
I would change the code like this (edited as suggested in comment)
var customers = [{
fullName: 'Marshall Hathers',
dob: '01/07/1970'
}, {
fullName: 'Margaret May',
dob: '01/07/1980'
}];
function findCustomer(customer) {
for (i = 0; i < customers.length; i++) {
if (customer === customers[i].fullName) {
console.log('Customer has been found');
return true;
}
}
console.log('Customer has not been found');
return false;
}
findCustomer('Marshall Haters');
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.
I am attempting to display a javascript object's "text" property to display in the console when its timecode property is reached. The "timecode" property is being compared to elapsed time in a Vimeo player. That's fine and well—the issue I am having is due to the Vimeo API returning multiple millisecond data 'hits' per second, so I see my text pop up multiple times in the console.
Can anyone suggest how to display each text property once, and only once?
notes_ex = [
{
timecode: 2,
text: 'Hi there!'
},
{
timecode: 7,
text: 'Hi again!'
}
];
function ready(player_id) {
var player = $f(player_id);
player.addEvent('ready', function() {
console.log('ready');
player.addEvent('playProgress', onPlayProgress);
});
function onPlayProgress(data, id) {
timeElapsed = Math.floor(data.seconds);
console.log('timeElapsed:' + timeElapsed);
while (timeElapsed++) {
for (var i = 0; i < notes_ex.length; i++) {
timecode = notes_ex[i].timecode;
if (timecode === timeElapsed) {
console.log(notes_ex[i].text);
}
}
break;
}
}
Would you just be able to assign a second variable to denote when it's been triggered? So something like this:
var z = 0;
if (timecode === timeElapsed && z == 0) {
console.log(notes_ex[i].text);
z++;
}
A bit incomplete, but you get the principle...