Nested Object array values - javascript

I am utilizing jquery to loop thru 'searchResults' and looping thru 'SearchResult' and then looping again into 'SearchResultItems' to begin appending values. I then locate 'LocationDetails' and loop thru the nested values of State to display states for each 'DisplayTitle'.
If that description isn't well written, here is the code.
searchResults = [{
"SearchResult": {
"SearchResultItems": [{
"MatchedObjectDescriptor": {
"URI":"http://...",
"DisplayTitle": "Boss Person",
"LocationDetails": [{
"State": "California",
"CityName": "San Francisco County, California",
},{
"State": "Colorado",
"LocationName": "Denver, Colorado",
},{
"State": "California",
"CityName": "Los Angeles, California",
}]
}
},{
"MatchedObjectDescriptor": {
"URI":"http://...",
"DisplayTitle": "Assistant",
"LocationDetails": [{
"State": "Colorado",
"CityName": "Denver, Colorado",
},{
"State": "Colorado",
"LocationName": "Denver, Colorado",
},{
"State": "California",
"CityName": "Sacramento, California",
}]
}
},
]
}
}];
My current attempt at navigating the array of objects.
$.each(searchResults, function(key,value){
$.each(value.SearchResult.SearchResultItems,function(key,value){
var items = value.MatchedObjectDescriptor,
title = items.DisplayTitle;
$.each(items.LocationDetails, function(key,value){
var states = value.State;
$(".content").append("<ul><li>'" + title + "'<ul><li>'" + states + "'</li></ul></li></ul>");
});
});
});
See my work here so far with the wrong output: https://jsfiddle.net/arkjoseph/esvgcos7/15/
I am looking for this output filtering duplicate states and not having a different title for each state that is available in the object.
Boss person
California
Colorado
Assistant
Colorado
California

This gives you expected output.
searchResults = [{
"SearchResult": {
"SearchResultItems": [{
"MatchedObjectDescriptor": {
"URI": "http://...",
"DisplayTitle": "Boss Person",
"LocationDetails": [{
"State": "California",
"CityName": "San Francisco County, California",
}, {
"State": "Colorado",
"LocationName": "Denver, Colorado",
}, {
"State": "California",
"CityName": "Los Angeles, California",
}]
}
}, {
"MatchedObjectDescriptor": {
"URI": "http://...",
"DisplayTitle": "Assistant",
"LocationDetails": [{
"State": "Colorado",
"CityName": "Denver, Colorado",
}, {
"State": "Colorado",
"LocationName": "Denver, Colorado",
}, {
"State": "California",
"CityName": "Sacramento, California",
}]
}
}, ]
}
}];
var states = "";
$.each(searchResults, function(key, value) {
$.each(value.SearchResult.SearchResultItems, function(key, value) {
var items = value.MatchedObjectDescriptor,
title = items.DisplayTitle;
var s = [];
var li = "";
$.each(items.LocationDetails, function(key, value) {
var states = value.State;
if (!s.includes(states)) {
s.push(states);
li += ("<li>" + states + "</li>")
}
});
$(".content").append("<ul><li>" + title + "<ul>" + li + "</ul></li></ul>");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<div class="content"></div>
actual json endpoint: <a target="_blank" href="https://pastebin.com/embed_js/dRfMedYb">Here</a>

A working version of your code is as follows. This is just one example of how to do it, but using Set in ES6 (if you have an environment where it's permitted or are using a transpiler like Babel) might be desirable. Either way, this just appends to an array and joins on an empty string at the end to create your nodes. Using jQuery to build your elements also will likely be more scalable down the road, but for a small app the following works.
searchResults = [{
"SearchResult": {
"SearchResultItems": [{
"MatchedObjectDescriptor": {
"URI":"http://...",
"DisplayTitle": "Boss Person",
"LocationDetails": [{
"State": "California",
"CityName": "San Francisco County, California",
},{
"State": "Colorado",
"LocationName": "Denver, Colorado",
},{
"State": "California",
"CityName": "Los Angeles, California",
}]
}
},{
"MatchedObjectDescriptor": {
"URI":"http://...",
"DisplayTitle": "Assistant",
"LocationDetails": [{
"State": "Colorado",
"CityName": "Denver, Colorado",
},{
"State": "Colorado",
"LocationName": "Denver, Colorado",
},{
"State": "California",
"CityName": "Sacramento, California",
}]
}
},
]
}
}];
var states = [];
var output = [];
$.each(searchResults, function(key,value){
output.push("<ul>")
$.each(value.SearchResult.SearchResultItems,function(key,value){
var items = value.MatchedObjectDescriptor,
title = items.DisplayTitle;
output.push("<li>" + title + "</li>")
output.push("<ul>")
$.each(items.LocationDetails, function(key,value){
if (states.filter(s => s == value.State).length) return;
states.push(value.State)
output.push("<li>" + value.State + "</li>")
});
states = []
output.push("</ul>")
});
output.push('</ul>')
});
$(".content").append(output.join(''));

Related

Remove JSON parent element in JavaScript

I'm currently trying to code an application with javascript. It pulls data from a database and the response I'm getting is something like that:
{
"values":[
{
"name": "Munich",
"location": "Germany",
"native_lang": "German",
},
{
"name": "London",
"location": "England",
"native_lang": "English",
},
{
"name": "Rome",
"location": "Italy",
"native_lang": "Italian",
}
]
}
But I need to have the JSON like that:
[
{
"name": "Munich",
"location": "Germany",
"native_lang": "German",
},
{
"name": "London",
"location": "England",
"native_lang": "English",
},
{
"name": "Rome",
"location": "Italy",
"native_lang": "Italian",
}
]
How can I delete the parent values object in my JSON?
SHORT ANSWER:
Just access the values property like a JavaScript object.
LONG ANSWER:
You didn't post the JavaScript code snippet so it's quite difficult to give you an appropriate answer.
Assuming you have the following code:
const jsonString = getDataFromTheDB()
const jsonObject = JSON.parse(jsonObject) // still has the "values" layer
const values = jsonObject.values // what you want, without the "values" layer
// BONUS: Just in case you want to convert the object back to a JSON string but without the "values" layer
const valuesJSON = JSON.stringify(values, undefined, 2)
Based on this post :
just do this (consider json the variable that contains your json):
var key = "values";
var results = json[key];
delete json[key];
json = results;
console.log(json) will output the following:
[
{
"name": "Munich",
"location": "Germany",
"native_lang": "German",
},
{
"name": "London",
"location": "England",
"native_lang": "English",
},
{
"name": "Rome",
"location": "Italy",
"native_lang": "Italian",
}
]
But you dont even have to do the last 2 steps of the code snippet above, you could also just directly use results variable and have the same output by console.log(results).
You could take the object and create a new variable with just the array.
var vals =
{
"values":[
{
"name": "Munich",
"location": "Germany",
"native_lang": "German",
},
{
"name": "London",
"location": "England",
"native_lang": "English",
},
{
"name": "Rome",
"location": "Italy",
"native_lang": "Italian",
}
]
}
var arr = vals.values;
console.log(arr);

loop over array of objects based on the keywords

Sort the array of objects by the certain order.
var details = [{
"name": "john",
"place":"new york"
},{
"name": "mark",
"place":"chicago"
},{
"name": "tom",
"place":"san jose"
},{
"name": "dansk",
"place":"new jersey"
}],
The map should show a list in following order, basically we need to decide the pattern of output, we should be able to change the order:
san jose,
new york,
chicago,
new jersey
I tried this:
details.sort((a, b)=> a.place - b.place)).map((data) => {
return(
<div>
<li>{data.place}</li>
</div>
)})
For sort array based on other Array, you can you this code
var details = [{
"name": "john",
"place": "new york"
}, {
"name": "mark",
"place": "chicago"
}, {
"name": "tom",
"place": "san jose"
}, {
"name": "dansk",
"place": "new jersey"
}];
var sortingArray = ["san jose", "new york", "chicago", "new jersey"];
var result = [];
sortingArray.forEach(function (key) {
var found = false;
details = details.filter(function (item) {
if (!found && item.place == key) {
result.push(item);
found = true;
return false;
} else
return true;
})
})
console.log(result);
After rearranging array you can map
result.map((data) => {
return (
<div>
<li>{data.place}</li>
</div>
)
})
I don't see any logic in the order these items should be sorted, so I'd go with a list that defines the order for the sorting.
let order = ["san jose", "new york", "chicago", "new jersey"];
var details = [{
"name": "john",
"place": "new york"
},
{
"name": "mark",
"place": "chicago"
},
{
"name": "tom",
"place": "san jose"
},
{
"name": "dansk",
"place": "new jersey"
}]
.sort((a,b) => order.indexOf(a.place) - order.indexOf(b.place));
console.log(details);

Query JSON data sharing same value

Sample JSON Data:
{
"results": [
{
"name": "John Smith",
"state": "NY",
"phone": "555-555-1111"
},
{
"name": "Mary Jones",
"state": "PA",
"phone": "555-555-2222"
},
{
"name": "Edward Edwards",
"state": "NY",
"phone": "555-555-3333"
},
{
"name": "Abby Abberson",
"state": "RI",
"phone": "555-555-4444"
},
]}
With this sample data I can display individual values from the results [] array with object.name and object.phone to look something like:
John Smith 555-555-1111<br />
Mary Jones 555-555-2222<br />
Edward Edwards 555-555-3333<br />
Abby Abberson 555-555-4444
What I am trying to do now is select just the people who's state value is NY and only display their object.name and object.phone:
John Smith 555-555-1111<br />
Edward Edwards 555-555-3333
I tried this lovely little block but all it did was print all the names, which makes sense after I tried it.
if (object.state = "NY") {
div.append(repName);
}
I can't seem to think of a way to only display those that share a the same state.
I'm probably searching for the wrong terms or have to go about this another way... please help!
You are using =(assignment operator),which is wrong.
You have to use ==(comparison operator)
So do like below:-
if (object.state == "NY") {
div.append(repName);
}
Working sample-
var obj = {
"results": [
{
"name": "John Smith",
"state": "NY",
"phone": "555-555-1111"
},
{
"name": "Mary Jones",
"state": "PA",
"phone": "555-555-2222"
},
{
"name": "Edward Edwards",
"state": "NY",
"phone": "555-555-3333"
},
{
"name": "Abby Abberson",
"state": "RI",
"phone": "555-555-4444"
},
]};
$(obj.results).each(function(k,object){
if (object.state == "NY") {
$('#final_data').append(object.name +" : "+object.phone+"<br/>");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="final_data"></div>
My one cent solution:
var obj = {
"results": [
{
"name": "John Smith",
"state": "NY",
"phone": "555-555-1111"
},
{
"name": "Mary Jones",
"state": "PA",
"phone": "555-555-2222"
},
{
"name": "Edward Edwards",
"state": "NY",
"phone": "555-555-3333"
},
{
"name": "Abby Abberson",
"state": "RI",
"phone": "555-555-4444"
},
]};
obj.results.forEach((value) => {
if (value.state === "NY") {
const li = document.createElement("li");
li.innerHTML = `${value.name} : ${value.phone}`;
document.querySelector("#final_data").appendChild(li);
}
});
<ul id="final_data"></ul>
Like Alive said you used the assignment operator = instead of comparison operator === or ==.

Deeper understanding of Promises

In my controller, I have a branches array in which I need to append location object containing lat long to each item of it i.e.
{
"BANK": "B N P PARIBAS",
"IFSC": "BNPA0009009",
"MICR CODE": "400034002",
"BRANCH": "MUMBAI",
"ADDRESS": "FRENCH BANK BLDG.,62, HOMJI STREET, MUMBAI - 400 001",
"CONTACT": "0",
"CITY": "MUMBAI",
"DISTRICT": "MUMBAI",
"STATE": "MAHARASHTRA",
"ZIPCODE": "400 001",
"location": {
lat: ,
long:
}
},
I am doing so by iterating the branches vi angular forEach and calling the getLatLong function on each item inside forEach loop.
However, the control/execution of the function is such that it return deferred.promise before I have got any results from service call. Ideally I want to have the location object from google maps API and then when it resolves I want the results back to controller function getLatLong and return that location object which in turn be assigned to item.location in forEach loop.
My controller
module.exports = function(AppFactory, $q){
'use strict';
let ctrl = this;
ctrl.showList = true;
ctrl.branches = [
{
"BANK": "B N P PARIBAS",
"IFSC": "BNPA0009008",
"MICR CODE": "700034002",
"BRANCH": "KOLKATA",
"ADDRESS": "UNIT NO. 301, OFFICE NO. 2, 3RD FLOOR, AVANI SIGNATURE,91A/1, PARK STREET,KOLKATA :- 700016",
"CONTACT": "0",
"CITY": "KOLKATA",
"DISTRICT": "KOLKATA",
"STATE": "WEST BENGAL",
"ZIPCODE": "700016"
},
{
"BANK": "B N P PARIBAS",
"IFSC": "BNPA0009009",
"MICR CODE": "400034002",
"BRANCH": "MUMBAI",
"ADDRESS": "FRENCH BANK BLDG.,62, HOMJI STREET, MUMBAI - 400 001",
"CONTACT": "0",
"CITY": "MUMBAI",
"DISTRICT": "MUMBAI",
"STATE": "MAHARASHTRA",
"ZIPCODE": "400 001"
},
{
"BANK": "B N P PARIBAS",
"IFSC": "BNPA0009065",
"MICR CODE": "110034002",
"BRANCH": "DELHI",
"ADDRESS": "1ST FLOOR EAST TOWER (SOOD TOWER), 25, BARAKHAMBA ROAD,NEW DELHI :- 110001",
"CONTACT": "0",
"CITY": "DELHI",
"DISTRICT": "DELHI",
"STATE": "DELHI",
"ZIPCODE": "110001"
},
{
"BANK": "B N P PARIBAS",
"IFSC": "BNPA0009067",
"MICR CODE": "560034002",
"BRANCH": "BANGALORE",
"ADDRESS": "3RD FL,LANDMARK,21/15,M.G.ROAD,BANGLORE-560 001",
"CONTACT": "0",
"CITY": "BANGALORE",
"DISTRICT": "BANGALORE",
"STATE": "KARNATAKA",
"ZIPCODE": "560 001"
},
{
"BANK": "B N P PARIBAS",
"IFSC": "BNPA0009069",
"MICR CODE": "411034002",
"BRANCH": "PUNE",
"ADDRESS": "5 & 6,GODREJ MILLENIUM PARK,9,KOREGAON ROAD,PUNE-411 001",
"CONTACT": "0",
"CITY": "PUNE",
"DISTRICT": "PUNE",
"STATE": "MAHARASHTRA",
"ZIPCODE": "411 001"
}
]
// console.log(ctrl.branches);
function getLatLong(addressOrZip){
let results;
let deferred = $q.defer();
AppFactory.getLatLong(addressOrZip).then(function(res){
console.log(res);
deferred.resolve(res);
// if(res.results.length > 0){
// results = res.results[0].geometry.location;
// }else{
// results = res.results;
// }
// return results;
}, function(error){
deferred.reject(res);
});
return deferred.promise;
}
ctrl.toggleViews = function(){
ctrl.showList = !ctrl.showList;
if(!ctrl.showList){
angular.forEach(ctrl.branches, function(item){
let location = getLatLong(item.ZIPCODE );
console.log(location);
// let location = getLatLong( item.ADDRESS || item.ZIPCODE );
// if(location){
// item.location = location;
// }
})
console.log("Logging branches with location object...");
console.log(ctrl.branches);
}
}
}
Then in my AppFactory
let getLatLong = function(location){
// let defferred = $q.defer();
return $http({
url: "https://maps.googleapis.com/maps/api/geocode/json?address="+ location +"&key=AIzaSyDGyOrnNj8rrRFR92m6BEMvR24JiYoHtMs"
}).then(function(response){
return response.data;
// defferred.resolve(response.data);
}, function(error){
return error;
// defferred.reject(error);
});
// return defferred.promise;
}
How can I get around this ?
getLatLong() returns a promise (which is what $http returns) so you need to use then() on that returned promise to access the response data
Change:
let location = getLatLong(item.ZIPCODE );
console.log(location);
To:
getLatLong(item.ZIPCODE ).then(function(data){
item.location = data;
console.log(item.location);
});
Will leave it up to you to validate that error is not returned to this then()

Return just the keys of an array in AngularJS

I have a solution of my question, but I don't know whether it exists a better solution.
Following I had implemented:
View:
<md-list>
<md-list-item>
<span ng-repeat="item in ::items track by $index" flex="auto">
{{::item}}
</span>
<md-divider></md-divider>
</md-list-item>
</md-list>
Controller:
CrudSvc.GetAll().$promise.then(
function (res) {
$scope.items = GetKeyForTitle(res);
},
function (err) {
//err code...
}
);
function GetKeyForTitle(data) {
var arrItems = [];
var resData = data[0];
angular.forEach(resData, function (val, key) {
arrItems.push(key);
});
return arrItems;
}
JSON data is simple defined:
[
{
"NAME": "John Doe",
"AGE": 25,
"CITY": "New York",
"COUNTRY": "USA"
},...
]
For my solution I used data[0] to give me only the first data otherwise I get always the same keys and I need the keys just one time.
Use Object.keys():
var data = [{
"NAME": "John Doe",
"AGE": 25,
"CITY": "New York",
"COUNTRY": "USA"
}, {
"NAME": "John Doe",
"AGE": 25,
"CITY": "New York",
"COUNTRY": "USA"
}, {
"NAME": "John Doe",
"AGE": 25,
"CITY": "New York",
"COUNTRY": "USA"
}, {
"NAME": "John Doe",
"AGE": 25,
"CITY": "New York",
"COUNTRY": "USA"
}, {
"NAME": "John Doe",
"AGE": 25,
"CITY": "New York",
"COUNTRY": "USA"
}]
var arrItems = Object.keys(data[0]);
console.log(arrItems);
https://repl.it/E0lI
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
You can use
var allKeys = [];
for(var key in myObject) allKeys.push(k);
console.log("Keys " + allKeys.length + " keys: " + allKeys);
Or if you are using Lodash/underscore they it makes your life even easier.

Categories