How to loop through array and find if key - javascript

So basically I want o loop through an error (what i already did) and print the other key
var planet = "sun";
var planets = [{
type: "sun",
desc: "sun"
}, {
type: "moon",
desc: "moon"
}];
var pln = planets.length;
for (var i = 0; i < pln; i++) {
console.log(planets[i]);
}
How can i I find out if the var planet is in the array planets and print out the description from that key if so?

Compare planet with current planets[i].type. Once planet is found in array remember to terminate loop using break keyword:
var pln = planets.length;
for (var i = 0; i < pln; i++) {
if (planets[i].type === planet) {
console.log(planets[i].desc);
break;
}
}

You could use filter
var planet = "sun";
var planets = [{
type: "sun",
desc: "sun"
}, {
type: "moon",
desc: "moon"}];
var planetObj = planets.filter(function(obj){
return obj.type==planet;
})[0].desc;//sun
If you are unsure if planet exists, you may wish to see if the array returned from filter actually contained any elements, or perhaps iterate the returned set if there were more than one you were searching for.

Hmm, I think this is what you want:
var pln = planets.length;
for (var i = 0; i < pln; i++) {
if (planets[i].type == planet) {
console.log(planets[i].desc);
break;
}
}

Related

Find whether an array has a substring corresponding to another element in a new array JS

I get the value of "name" from a promise and I store it in an array as it MAY contain multiple names.
var name = ["Arun_Manohar"];
var combinations = ["abc", "def", "ghi", "har", "lmn"];
Lets say I have an activities object.
var activities = {
driving: false,
jogging: false,
drinking: false
}
How do I go about writing a check to update the activities object in this case.
NOTE: No two elements in combinations array will be a substring of names array. Just one.
Case: Since name contains a substring of one of the elements of combinations, I need to update the activities object. If the name contains a substring like "abc", I will update the object with different values.
Use of lodash would be great.
Tried something and wasnt able to update the object.
if(name.indexOf(_.filter(combinations, function(e) { return.indexOf("har") !== -1})) !== -1) {
activities.driving= true;
activities.jogging= true;
}
If the name contains "abcpoc", since the substring is present in combinations array, I update the object with a different set of values.
If you're using lodash, you can use _.intersectionWith, using a comparator function that uses indexOf().
matched_combos = _.intersectionWith(combinations, names, (combo, name) => name.indexOf(combo) != -1);
Then you can loop through matched_combos to add appropriate things to activities:
matched_combos.forEach(str => {
switch(str) {
"har":
activities.driving = true;
activities.jogging = true;
break;
...
}
});
var names = ["Arun_Manohar"];
var combos = ["abc", "def", "ghi", "har", "lmn"];
var activities = {};
for (var i = 0; i < names.length; i++) {
for (var j = 0; j < combos.length; j++) {
if (names[i].indexOf(combos[j]) >= 0) {
activities.driving = true; //or whatever you need here;
}
}
}
Yo can also extend this code with additional checks and continue/break statements to avoid additional unnecessary loops if corresponding substring was already found.
Here is ES5 solution with indexOf:
var names = ["Arun_Manohar"];
var combinations = ["abc", "def", "ghi", "har", "lmn"];
var activities = {
driving: false,
jogging: false,
drinking: false
}
for (var i = 0; i < names.length; i++) {
for (var j = 0; j < combinations.length; j++) {
if(names[i].indexOf(combinations[j]) >= 0) {
activities.name = names[i]
}
}
}
console.log(activities);
And here is ES6 solution with includes:
var names = ["Arun_Manohar"];
var combinations = ["abc", "def", "ghi", "har", "lmn"];
var activities = {
driving: false,
jogging: false,
drinking: false
}
for (var i = 0; i < names.length; i++) {
for (var j = 0; j < combinations.length; j++) {
if(names[i].includes(combinations[j])) {
activities.name = names[i]
}
}
}
console.log(activities);
And here is more elegant ES6 solution with includes, forEach iterating method and arrow functions:
var names = ["Arun_Manohar"];
var combinations = ["abc", "def", "ghi", "har", "lmn"];
var activities = {
driving: false,
jogging: false,
drinking: false
}
names.forEach(item1 => {
combinations.forEach(item2 => {
if(item1.includes(item2)) {
activities.name = item1;
}
});
});
console.log(activities);

How to extract total instance of a variable in a array and its first properties

I have got a fruits array as shown below
var fruits = [
{
"buyprice": "10",
"sellprice": "11",
"name": "pomogranate"
},
{
"buyprice": "10",
"sellprice": "11",
"name": "apple"
},
{
"buyprice": "12",
"sellprice": "13",
"name": "orange"
},
{
"buyprice": "14",
"sellprice": "15",
"name": "apple"
}
]
I want to find out the total counts of apple present in the array
and the buy price and sellprice of the first element of the apple present in the array (not the last element)
I have tried it this way
function findnumberofaccourences(fruits, apple) {
var a = 0;
var buyprice;
var sellprice
for (var i = 0; i < fruits.length; i++) {
var name = fruits[i].name;
buyprice = fruits[i].buyprice;
sellprice = fruits[i].sellprice;
if (name == apple) {
a++;
}
}
var p = { count: a, buyprice: buyprice, sellprice: sellprice };
return p;
}
var result = findnumberofaccourences(fruits, 'apple');
alert(JSON.stringify(result));
But when i run this i am getting the result as (the buyprice and sellprice of apple's last element , where as i need apples first element )
{"count":2,"buyprice":"14","sellprice":"15"}
This is my fiddle
http://jsfiddle.net/thkc0fpk/2/
could you please elt em know how to achive this
A few things:
As Hacketo said, only grab the prices when a == 0.
Also, only grab the price for apples, rather than all fruit.
Calling the argument giving the fruit name to find apple is a bit misleading (since it could contain the string pear). Perhaps fruitName or similar instead?
Here's a minimal-changes example:
function findnumberofaccourences(fruits, fruitName) {
var a = 0;
var buyprice;
var sellprice;
for (var i = 0; i < fruits.length; i++) {
var name = fruits[i].name;
if (name == fruitName) { // Only apples
if (a == 0) { // Only the first
buyprice = fruits[i].buyprice;
sellprice = fruits[i].sellprice;
}
a++;
}
}
var p = {
count: a,
buyprice: buyprice,
sellprice: sellprice
};
return p;
}
var result = findnumberofaccourences(fruits, 'apple');
alert(JSON.stringify(result));
You can also simplify a fair bit, using the more-modern forEach and using the object you're going to return directly:
function findnumberofaccourences(fruits, fruitName) {
var p = {
count: 0,
buyprice: undefined,
sellprice: undefined
};
fruits.forEach(function(fruit) {
if (fruit.name == fruitName) {
if (p.count == 0) {
p.buyprice = fruit.buyprice;
p.sellprice = fruit.sellprice;
}
p.count++;
}
});
return p;
}
var result = findnumberofaccourences(fruits, 'apple');
alert(JSON.stringify(result));
You can filter apples first into an array, then retrieve the first element of this array to get the data you need.
var apples = fruits.filter(function (fruit) {
return fruit.name === 'apple';
});
var p = {
count: apples.length,
buyprice: apples[0].buyprice,
sellprice: apples[0].sellprice
};
Just reverse the array first
var price = {
count: 0
};
fruits.reverse().forEach(function (fruit) {
if (fruit.name === "apple") {
price.count++;
price.buyprice = fruit.buyprice;
price.sellprice = fruit.sellprice;
}
})
console.log(price)
// restore original order in fruits array (if you are going to use it)
fruits.reverse();
Note that this will reverse your array in place, so you'll need to do a fruits.reverse() once again to get back the fruits array elements in the original order, if you are going to use fruits further down the flow. (Thanks aduch)
Well your code does not work as you expect, your example work only because apple is the last element of the array.
you need to update your for loop like this
for (var i = 0; i < fruits.length; i++) {
var name = fruits[i].name;
if (name == apple) {
if ( a === 0){
buyprice = fruits[i].buyprice;
sellprice = fruits[i].sellprice;
}
a++;
}
}
It will update buyprice and sellprice only the first time for the first apple
Your orignal code was updating buyprice and sellprice for each element of your array

Combine arrays into nested objects

So this is a little trippy, but here goes.
Let's say I have two arrays-- a 1D array that contains set of of categories, and a 2D array that contains an arbitrary number of arrays whose contents follow the category templates established by the first array. For instance:
var categoryArray = ["Name", "Title", "Hire Date"];
var infoArray = [["John","Project Manager","January 5"], ["Alex","Accountant","December 15"], ["Joanne","Graphic Designer","August 26"]];
What I'd like to do is consolidate this information into a single object. So up top I drop:
var myDict = {};
My (obviously wrong) attempt was to have nested for-loops which go through each array and attempts to fill the myDict object with the contents of the arrays. It looks like this:
// Start by iterating by the length of the info array, so we assign a new sub-object to the myDict Object for each entry.
for (i = 0; i < infoArray.length; i++) {
// Each entry will be a new "row," like in a spreadsheet.
var row = String("row"+i);
// I'm guessing that the declaration below doesn't actually assign the "Row1", "Row2", etc as nested objects like I had intended, but just re-writes a child called "row"
myDict.row = {};
// Next we iterate through the number of categories we'll need-- and we'll pull from the length of our categoryArray so we can change the number of categories later.
for (x = 0; x < categoryArray.length; x++) {
// In theory, the first iteration of this will create a child of "row1" called "name," which will hold a value of "John" (so, the value stored infoArray[1][1])
myDict.row.categoryArray[x] = infoArray[i][x];
}
}
There's clearly a LOT wrong in there, but I'm totally scratching my head about how to approach this. I guess the key problem is trying to assign the actual strings held by variables/arrays as names for objects/children, but a thorough googling has produced no answers.
Save me oh mighty internet!
var result = infoArray.map(function(currentArray) {
return categoryArray.reduce(function(previous, currentKey, index) {
previous[currentKey] = currentArray[index];
return previous;
}, {});
});
Output
[ { Name: 'John',
Title: 'Project Manager',
'Hire Date': 'January 5' },
{ Name: 'Alex',
Title: 'Accountant',
'Hire Date': 'December 15' },
{ Name: 'Joanne',
Title: 'Graphic Designer',
'Hire Date': 'August 26' } ]
If your environment doesn't support Array.prototype.map function, you can use this
var result = [];
for (var i = 0; i < infoArray.length; i += 1) {
var tempObj = {};
for (var j = 0; j < categoryArray.length; j += 1) {
tempObj[categoryArray[j]] = infoArray[i][j];
}
result.push(tempObj);
}
Using row0, row1, etc. doesn't sound like a good idea. An array would make more sense. Anyway:
var categoryArray = ["Name", "Title", "Hire Date"];
var infoArray = [["John","Project Manager","January 5"],["Alex","Accountant","December 15"],["Joanne","Graphic Designer","August 26"]];
var myDict = {};
for (i = 0; i < infoArray.length; i++) {
// Each entry will be a new "row," like in a spreadsheet.
var row = {};
myDict["row"+i] = row;
// Next we iterate through the number of categories we'll need-- and we'll pull from the length of our categoryArray so we can change the number of categories later.
for (x = 0; x < categoryArray.length; x++) {
// In theory, the first iteration of this will create a child of "row1" called "name," which will hold a value of "John" (so, the value stored infoArray[1][1])
row[categoryArray[x]] = infoArray[i][x];
}
}
Output:
{
"row0": {
"Name": "John",
"Title": "Project Manager",
"Hire Date": "January 5"
},
"row1": {
"Name": "Alex",
"Title": "Accountant",
"Hire Date": "December 15"
},
"row2": {
"Name": "Joanne",
"Title": "Graphic Designer",
"Hire Date": "August 26"
}
}
// I'm guessing that the declaration below doesn't actually assign the "Row1", "Row2", etc as nested objects like I had intended, but just re-writes a child called "row"
myDict.row = {};
Exactly. For that, you will have to use
myDict[row] = {};
(and the same again below: myDict[row][…] = …)
// In theory, the first iteration of this will create a child of "row1" called "name," which will hold a value of "John" (so, the value stored infoArray[1][1])
myDict.row.categoryArray[x] = infoArray[i][x];
Again .categoryArray[x] is here used as a literal property name (the property x of the property "categoryArray", which does not exist) - you will have to wrap it in brackets.
You should end up with:
var myDict = {};
for (var i = 0; i < infoArray.length; i++) { // make iteration variables local
// with "var"
var row = "row"+i; // explicit String() call not necessary
myDict[row] = {};
for (var x = 0; x < categoryArray.length; x++) { // again, local "x"
myDict[row][categoryArray[x]] = infoArray[i][x];
}
}

Count distinct elements in array

I have data that comes from my server to datatables.
I'm successfully populating my table but in footer callback I want to do some statistics.
Lets say I have data like so:
var data = [{
date: '2013-05-12',
holiday: "One type of holiday",
dayType: "Weekend"
}, {
date: '2013-05-13',
holiday: "Another type",
dayType: "Weekend"
}, {
date: '2013-05-14',
holiday: "Another type",
dayType: "Work"
}, {
date: '2013-05-15',
holiday: "",
dayType: "Work"
}];
I would like to count number of days with different holidays.
Here is result I would like to get:
var summary= [
{
"One type of holiday": {
"work": 0,
"weekend": 1
}
},
{
"Another type": {
"work": 1,
"weekend": 1
}
}];
I've created a very simple code to simply aggregate holidays:
for (var i = 0; i < data.length; i++) {
//console.log(data[i].holiday);
/*other stuff here*/
if (data[i].holiday.length > 0)
summary[data[i].holiday] = summary[data[i].holiday] + 1 || 1;
}
but this gives me invalid results, because in my data array holiday contains spaces.
I need a way to fix this and to split holidays based on dayType.
MY SOLUTION:
My version of answer:
var summary = {}, d, tmp, type;
for (var i = 0; i < data.length; i++) {
var d = data[i];
if (d.holiday.length > 0) {
type = d.dayType == 'Weekend' || d.dayType == 'Free' ? 'Weekend' : 'Work';
tmp = summary[d.holiday];
if (!tmp) {
tmp = {
Weekend: 0,
Work: 0
};
summary[d.holiday] = tmp;
}
summary[d.holiday][type] += 1;
}
}
Because this is modified version of #Arun answer I'm not posting this as standalone answer.
I find my version easier to understand, hope someone find's it useful.
Try
var summary = [], summaryMap = {}, d, map, m;
for (var i = 0; i < data.length; i++) {
var d = data[i];
map = summaryMap[d.holiday];
if(!map){
map = {
Work: 0,
Weekend: 0
};
m = {};
m[d.holiday] = map;
summary.push(m);
summaryMap[d.holiday] = map;
}
map[d.dayType] += 1;
}
console.log(summary);
console.log(JSON.stringify(summary));
Demo: Fiddle
go for
console.log(Object.keys(summary).length);
instead of
console.log(summary.length);
Because you can get the number of elements in a js object by using the length attribute.
note: using Object.keys may lead you to browser compatibility issues. As its supported form IE 9 and Firefox 4. See more info in this MDN article.
you can find more info and solutions for this problem in this answer.
see the updated fiddle.
Here's my attempt:
var summary = [];
var holidayTypes = [];
var dayTypes = [];
//first work out the different types of holidays
for (var i = 0; i < data.length; i++) {
if(holidayTypes.indexOf(data[i].holiday) == -1){
//this is a new type of holiday
holidayTypes.push(data[i].holiday);
}
if(dayTypes.indexOf(data[i].dayType) == -1){
//new type of day.
dayTypes.push(data[i].dayType);
}
}
console.log('types of holiday: ' + JSON.stringify(holidayTypes));
console.log('types of day: ' + JSON.stringify(dayTypes));
for(index in holidayTypes){
var typeobj = {};
//create an object for each type of holiday
typeobj[holidayTypes[index]] = {};
for(index2 in dayTypes){
//initialize a count for each type of day
typeobj[holidayTypes[index]][dayTypes[index2]] = 0;
//iterate through the data and count the occurrences where the day AND holiday match.
//if they do, iterate the value.
for (var j = 0; j < data.length; j++){
if((data[j].holiday == holidayTypes[index])
&& (data[j].dayType == dayTypes[index2])){
typeobj[holidayTypes[index]][dayTypes[index2]]++;
}
}
}
summary.push(typeobj);
}
console.log(JSON.stringify(summary));
Fiddle here
Output:
[{"One type of holiday":{"Weekend":1,"Work":0}},{"Another type":{"Weekend":1,"Work":1}},{"":{"Weekend":0,"Work":1}}]
It works but is unlikely to be as efficient as the guys above!

loop a JS Object

I have this JS object:
{
"data": {
"nid": [{
"cid": "32",
"uid": "780",
"comment": "text"
}]
},
"request_status": "found"
}
how can I loop through these items to get comment value ("comment":"text")?
You don't really need to loop to get it. Just do...
var obj = {"data":{"nid":[{"cid":"32","uid":"780","comment":"text"}]},"request_status":"found"};
var text = obj.data.nid[0].comment;
Or if there are several, you can use forEach...
obj.data.nid.forEach(function(val,i) {
alert( val.comment );
});
Or a traditional for loop...
for( var i = 0; i < obj.data.nid.length; i++ ) {
alert( obj.data.nid[i].comment );
}
Or if you want to build an Array, use map...
var arr = obj.data.nid.map(function(val,i) {
return val.comment;
});
Or again a traditional for loop...
var arr = []
for( var i = 0; i < obj.data.nid.length; i++ ) {
arr.push( obj.data.nid[i].comment );
}
Given:
var obj = {
"data": {
"nid": [{
"cid": "32",
"uid": "780",
"comment": "text"
}]
},
"request_status": "found"
};
The direct way to retrieve the comment is:
obj["data"]["nid"][0]["comment"]
// or
obj.data.nid[0].comment
As far as "looping" through the items to get the value, I'm not sure how a loop makes sense. Are you saying you might not know the structure of the object but you know it will have a "comment" field in there somewhere?
The "nid" array only has one item in it - if this was just a sample but really you'll have an array with more values you can loop through that array:
var nid = obj["data"]["nid"], // get a direct reference to the array to save
i; // repeating obj.data.nid everywhere
for (i=0; i < nid.length; i++) {
// do something with the comment in the current item
console.log(nid[i]["comment"]);
}
If you're just referring to that specific object (or if every object you are working with follows that same pattern), then you can just access the value directly:
var theObj = {"data":{"nid":[{"cid":"32","uid":"780","comment":"text"}]},"request_status":"found"};
alert(theObj.data.nid[0].comment);
If you want to do something iterative, then perhaps try this:
var theObj = {"data":{"nid":[{"cid":"32","uid":"780","comment":"text"}]},"request_status":"found"};
for (var index = 0; index < theObj.data.nid.length; index++) {
var item = theObj.data.nid[index];
if (item.comment) {
alert(item.comment);
}
}
Or if you really want to do the entire thing iteratively:
window.searchObj = function(theObj) {
if (theObj.comment) {
alert(theObj.comment);
}
if (theObj instanceof Array) {
searchArray (theObj);
}
else if (theObj instanceof Object) {
for (var key in theObj) {
searchObj(theObj[key]);
}
}
};
window.searchArray = function(theArray) {
for (var index = 0; index < theArray.length; index++) {
var item = theArray[index];
searchObj(item);
}
};
var theObj = {"data":{"nid":[{"cid":"32","uid":"780","comment":"text"}]},"request_status":"found"};
searchObj(theObj);

Categories

Resources