iterating this response - javascript

{
'lastChangedName': null'Caption': 'Adhesive Tape',
'CreateByID': 0,
'DateOnSet': '02/10/2011',
'Note': 'Currently participating in Allergy shots to resolve this',
'Reaction': 'skin rash',
'SectionDescription': 'Allergy List',
'HistoryItemID': 1831,
'CurrentInDrFirst': 0,
'CreateDate': '/Date(1297674300000-0500)/',
'Code': '3746',
'PL': '1',
'Problem': {
"LastChargedByUserID": 0,
"LastChargedDate": null,
"ProblemStatus": 1003,
"DateResolved": "12\/2\/11",
"PatientID": 0,
"ProblemID": 1330
},
'CategoryDescription': null,
'CategoryID': 0,
'CodeSystem': 'FDBDRUG',
'SectionID': 3,
'LastChangedID': 0,
},
{
'lastChangedName': null'Caption': 'Cats',
'CreateByID': 0,
'DateOnSet': '6/4/1997',
'Note': '0',
'Reaction': 'Sneezing',
'SectionDescription': 'Allergy List',
'HistoryItemID': 1925,
'CurrentInDrFirst': 0,
'CreateDate': '/Date(1299176220000-0500)/',
'Code': '',
'PL': '1',
'Problem': {
"LastChargedByUserID": 0,
"LastChargedDate": null,
"ProblemStatus": 1002,
"DateResolved": null,
"PatientID": 0,
"ProblemID": 1331
},
'CategoryDescription': null,
'CategoryID': 0,
'CodeSystem': '',
'SectionID': 3,
'LastChangedID': 0,
}
This is the response i get, i want to iterate and print out the caption values... in a text box...
for each(var item in response) {
alert(item.caption)
}
This only prints me the first caption alone.

That response, as quoted, is awkward because you have a series of anonymous objects separated by commas (you might think it was invalid, but it's not, it's just unhelpful). (That's assuming you fix the 'lastChangedName': null'Caption' thing that symcbean pointed out in the comments; I assume that's a copy-and-paste error.) I think there must be more to it than what's quoted. (Is it, perhaps, inside [ and ], making it an array of objects?)
But generally speaking: Yes, for..in (not for each, just for) is used to loop through the names of the properties of an object, and once you have each name, you can use [] notation to retrieve the property value.
So if you can get a reference to each of those objects, you can use for..in to loop through the properties.
Example:
var obj, name;
obj = {
foo: "bar",
answer: 42
};
for (name in obj) {
console.log(name + ": " + obj[name]);
}
That will show
foo: bar
answer: 42
or
answer: 42
foo: bar
The order of the property names in the loop is not specified for generic objects like those in your example. (It's specified for Array objects: With Array objects it's guaranteed that any properties they have with purely numeric names — e.g., array indexes — will be iterated in numeric order. [Even then, if you have non-numeric properties on the array as well, it's undefined whether those will be before, after, or intermixed with, the numeric ones.])

Try:
for(var item in response) {
alert(response[item].caption)
}

Related

Javascript - Convert JSON Object Property Value from Array to String

I have an issue where an API call I'm using is sending objects with one property that contains a single array value (keys property in response below). Unfortunately I cannot use this format as I must abide by Nested arrays in order to use the outputted values in a separate application like so [[value1, value2, value3, value4],[value1, value2, value3, value4]]. I plan on asking a separate question to tackle the nested array section unless someone thinks it is an easy fix (I believe I should use .map to convert the object).
Here is the format of my objects (from console.log(searchQueries)):
[ { keys: [ 'hammer' ],
clicks: 1369,
impressions: 3151,
ctr: 0.4344652491272612,
position: 1.004443033957474 },
{ keys: [ 'woodmaking' ],
clicks: 207,
impressions: 6324,
ctr: 0.03273244781783681,
position: 4.35831752055661 },
{ keys: [ 'house trends' ],
clicks: 1,
impressions: 3,
ctr: 0.3333333333333333,
position: 4.666666666666666 },
{ keys: [ 'housing' ],
clicks: 1,
impressions: 36,
ctr: 0.027777777777777776,
position: 6.472222222222222 } ]
byProperty
Above response is passed from the following for-in loop the result of this API response array being nested in an object originally:
for (var prop in res){
searchQueries = res[prop];
console.log(searchQueries);
}
Would the JSON.stringify method or .toString('keys') achieve what I'm looking for?
If you want to turn keys from an array into a string, you just need to iterate over your array and make the change:
searchQueries.forEach(function (obj) { obj.keys = obj.keys[0] })
answer=Object.values(searchQueries).map(el=>{el.keys=el.keys[0];return Object.values(el)});
console.log(searchQueries);
https://jsbin.com/biyazunafu/1/edit?console
Loop over the main array, turn the Objects (el) keys array into a string, than turn the whole object into its values Array. However, Object.values is experimental, so may dont use this on the users side, instead use this code transpiled to ES5 :
answer=[];
for(key in searchQueries){
answer.push(searchQueries[key]);
}
answer=answer.map(function(el){
el.keys=el.keys[0];
var newel=[];
for(key in el){
newel.push(el[key]);
}
return newel;
});
1st Get the keys values
var keys = searchQueries.map(function(e){return e.keys;});
This will output :
[["hammer"], ["woodmaking"], ["house trends"], ["housing"]]
2nd: Concat the resulting array
var values = keys.join(',').split(',');
The result :
["hammer", "woodmaking", "house trends", "housing"]

Having trouble extracting value from Javascript object's multidimensonal array [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 6 years ago.
I'm attempting to use Javascript objects to work with some data. Here is the object itself (parsed from JSON) which is defined as accounts:
{
startIndex: 0,
pageSize: 20,
pageCount: 1,
totalCount: 1,
items: [
{
id: 123456,
emailAddress: 'test#test.com',
userName: 'test#test.com',
firstName: 'John',
lastName: 'Hancock',
customerSet: 'default',
commerceSummary: [
Object
],
contacts: [
Object
],
userId: '92834439c29389fj292',
notes: [
],
attributes: [
Object
],
segments: [
Object
],
taxExempt: false,
externalId: '2100010368',
isAnonymous: false,
auditInfo: [
Object
],
isLocked: false,
isActive: true,
hasExternalPassword: false,
customerSinceDate: 2016-06-23T18: 26: 46.000Z
}
]
}
While I can retrieve accounts.items without issue, I'm having some trouble retrieving individual values such as id or emailAddress from the item itself. Doing accounts.items[id] or accounts.items[emailAddress] does not work but I believe it's due to the fact that items can be more than 1 so I should be specifying the "first result" for items from that list. If that is the case, how do I retrieve the emailAddress or id for the first items array? The desired result from the above JSON object should be "123456" if id and "test#test.com" if email. Thanks in advance.
Your items is an array. You have to fetch data from it by indexes (like items[0]). If you are looking for an item, with their properties, use Array.find method.
The find method executes the callback function once for each element
present in the array until it finds one where callback returns a true
value. If such an element is found, find immediately returns the value
of that element. Otherwise, find returns undefined. callback is
invoked only for indexes of the array which have assigned values; it
is not invoked for indexes which have been deleted or which have never
been assigned values.
var accounts = {
startIndex: 0,
pageSize: 20,
pageCount: 1,
totalCount: 1,
items: [
{
id: 123456,
emailAddress: 'test#test.com',
userName: 'test#test.com',
firstName: 'John',
lastName: 'Hancock',
customerSet: 'default'
}
]
};
var sampleAccount = accounts.items.find(function (item) {
return item.id == 123456;
});
if (sampleAccount) {
console.log(sampleAccount.emailAddress);
}
You are right, first you need to reference the first element of the array. Then you can query its properties.
For example, to get the ID and email address of the first item you would write
accounts.items[0].id
accounts.items[0].emailAddress
Arrays elements start at index 0 in JavaScript, so the first element of the array has index 0, the second 1, and so on.
Items is an array and emailAddress is a Key, then you can get the value using:
accounts.items[0].emailAddress

JS | lodash : recursive delete from deep nested array

Below is a recursive method to delete a comment from a deeply nested array. The code works, but here are my question:
QUESTION:
I'm using _.remove within the loop to find and remove a comment in the current array. It seems expensive for obvious reasons i.e. loop within a loop, but other approaches seems just as expensive. I'm sure there are better ways to do this.
WORKING EXAMPLE:
https://plnkr.co/edit/PeW5ZFLynO2q8VNqbAHx?p=preview
var comments = [
{
id: 1,
depth: 0,
subject: 'Subject one'
},
{
id: 2,
depth: 0,
subject: 'Subject two',
children: [
{
id: 3,
depth: 1,
subject: 'Subject two dot one'
},
{
id: 4,
depth: 1,
subject: 'Subject two dot two'
}
]
},
{
id: 5,
depth: 0,
subject: 'Subject three',
children: [
{
id: 6,
depth: 1,
subject: 'Subject three dot one'
},
{
id: 7,
depth: 1,
subject: 'Subject three dot two',
children: [
{
id: 8,
depth: 2,
subject: 'Subject three dot two dot one'
},
{
id: 9,
depth: 2,
subject: 'Subject three dot two dot two'
}
]
}
]
}
];
function deleteComment(comment, comments) {
var self = this,
db = [];
function removeComment(items, parent) {
_.forEach(items, function (item) {
// QUESTION - seems expensive as we have a loop in a loop
_.remove(items, function(item) {
if (item.id === comment.id) {
console.log(item);
return true;
}
// NOTE: use above for demo purposes
// return item.id === comment.id
});
_.has(item, 'children') ? removeComment(item.children, item) : 0;
});
}
removeComment(comments, db);
}
var commentToBeDeleted = {
id: 8,
depth: 2,
subject: 'Subject three dot two dot one'
};
deleteComment(commentToBeDeleted, comments);
You could probably find a way to do this more efficiently with a .reduce() function to combine .forEach and _.remove. However, if the code works, it works!
I am not sure if this is the most performant way to accomplish this, but this is the most succinct way I have found:
It turns out JSON.stringify provides a callback for each visited JSON value being converted, which you can use to determine if the value should be included in the string. You can use this to visit each value without having to do the traversing yourself.
From MDN
The replacer parameter can be either a function or an array. As a
function, it takes two parameters, the key and the value being
stringified. The object in which the key was found is provided as the
replacer's this parameter. Initially it gets called with an empty key
representing the object being stringified, and it then gets called for
each property on the object or array being stringified. It should
return the value that should be added to the JSON string,
In your case the function would look something like
function deleteComment(commentToBeDeleted, comments) {
return JSON.parse(JSON.stringify(comments, function(key, value) {
if (commentToBeDeleted.id !== value.id) {
return value;
}
}));
}
Note: you probably don't want to use this code as is, as it leaves an empty node, but, you can insert what ever you logic you like into the callback, and this should get you started.

Making a count object by initializing properties from iterating through elements in an array

Alright, so I'm working on the final problem of javascript-koans. The code and dataset I'm given are as follows:
products = [
{ name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
{ name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
{ name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
{ name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
{ name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
];
it("should count the ingredient occurrence (imperative)", function () {
var ingredientCount = { "{ingredient name}": 0 };
for (i = 0; i < products.length; i+=1) {
for (j = 0; j < products[i].ingredients.length; j+=1) {
ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
}
}
expect(ingredientCount['mushrooms']).toBe();
});
I think I understand some of what's going on: We're iterating through the products array to iterate through the ingredients array of each product, taking an ingredient, and using bracket notation to call it as a property from the ingredientCount object. But around here is where I'm losing it, because then we set it equal to itself or zero, then add one regardless. Can someone correct me on what I have wrong there and explain what I'm missing? How/where does calling the ingredientCount variable with 'mushrooms' in bracket notation establish 'mushrooms' in this expression? And how are we incrementing the ingredientCount's {ingredient name} property without explicitly referencing it? Is there some kind of implicit assignment or something going on?
Also, the test runner returns an error letting me know the expected result should be 2.
I figured it out. I was right in my written summation of that code, except what we're looking at in this code isn't just an expression, more importantly it's a variable assignment. So on each iteration through each ingredient of each product we're initializing a new property in the ingredientCount object and setting it equal to itself or zero. But why do that? Because if you set a non-existent object's property equal to itself you get undefined--it doesn't initialize. Luckily, undefined is a falsey value, and so if the property is non-existent it instead gets initialized by being set to zero, then incremented to one. After that each additional count for each existing ingredient takes the truthy numerical value (skipping the zero after the or) and adds one. So when we look at the result from the console, we see the ingredientCount object isn't behaving like a function (as I was confused in thinking it had been), instead it's a simple object with properties that we can access to give us their individual counts:
[object Object] {
artichoke: 1,
black beans: 1,
blue cheese: 1,
garlic: 1,
goats cheese: 1,
jalapenos: 1,
kalamata olives: 1,
mushrooms: 2,
roma: 1,
rosemary: 1,
sesame seeds: 1,
spinach: 1,
sundried tomatoes: 2,
walnuts: 1
{ingredient name}: 0
}
{ingredient name} was just in the code as a placeholder, which is why it shows up there at the bottom.

Search through an array of objects looking for non empty objects JS

At the core of the problem I have:
[
{amount: 0, name: "", icon: "", description: ""} // default object added to array
{amount: 1, name: "kjfhdkfjh", icon: "67", description: "dasdasd"}
]
I want to know how to use lodash find such that, as long as any key has a value other then 0 or "" we are not considered "empty".
So in this case lodash find would return:
[
{amount: 1, name: "kjfhdkfjh", icon: "67", description: "dasdasd"}
]
Or it would return undefined.
What I have is:
lodashFind(theArray, function(obj){
// Now what? How do I go through the objects?
});
I am not sure how to go through objects saying, as long as there is no 0 for amount and no string has "" then return that object.
Ideas?
Use _.filter, _.some, _.all or _.negate of lodash to achieve this:
var data = [
{ name:'a', age:0 },
{ name:'b', age:1 },
{ name:'', age:0 }
];
// lists not empty objects (with at least not empty field)
console.log(_.filter(data, _.some));
// outputs [{name:'a',age:0},{name:'b',age:1}]
// lists 'full' objects (with no empty fields)
console.log(_.filter(data, _.all));
// outputs [{name:'b',age:1}]
// lists 'empty' objects (with only empty fields)
console.log(_.filter(data, _.negate(_.some)));
// outputs [{name:'',age:0}]
_.some and _.all search for truthy values, '' and 0 is not truthy. Namely, the following JavaScript values are falsy: false, 0, '', null, undefined, NaN. Every other value is truthy.
Using just regular javascript, this is quite easy as well, just filter the array based on the objects values etc, like this
var arr = [
{amount: 0, name: "", icon: "", description: ""},
{amount: 1, name: "kjfhdkfjh", icon: "67", description: "dasdasd"}
]
arr = arr.filter(function(o) {
return Object.keys(o).filter(function(key) {
return o[key] != 0 && o[key].toString().trim().length > 0;
}).length > 0;
});
FIDDLE

Categories

Resources