Javascript Array Object iteration of properties - javascript

After reading many Stackoverflow questions, blogs, and documentation I still cannot figure out why this particular iteration over any array is not working.
I am using jQuery and javascript(obviously) to pull a GeoJSON file and then going over the properties of the resulting object to pull desired key/value pairs. As I find those pairs I want to insert then into another array object. The object is created as I expected however when I attempt to go over the newly created object nothing happens and if I try to find its length it returns a length of 0.
This is where I pull the records:
_recordsFromGeoJSON: function(inputText) {
var retRecords = {},
$.getJSON(this.GeoJSONUrl, function(data) {
var geoJSONdata = data;
$.each(geoJSONdata.features, function(fkey, fvalue) {
$.each(fvalue.properties, function(pkey, pvalue) {
var re = new RegExp(inputText, "i");
var retest = re.test(pvalue);
if (retest) {
retRecords[pvalue] = fvalue.geometry.coordinates;
return;
}
});
});
});
return retRecords;
},
This is the code for the interation over the new object:
for(var key in this._retRecords) {
//this function will never run
var always = foo(bar);
}
Some sample GeoJSON:
{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "id": 0, "properties": { "NAME": "14 PARK PLACE PH 4", "AREAID": 3.0, "STR12M": 0.0, "CLS12M": 6.0, "STR4M": 0.0, "CLS4M": 0.0, "TOTAL": 164.0, "OCC": 112.0, "NFU": 0.0, "UNC": 3.0, "DVL": 49.0, "UDVL": 0.0 }, "geometry": { "type": "Point", "coordinates": [ -93.27512816536759, 37.044305883435001 ] } }
,
{ "type": "Feature", "id": 1, "properties": { "NAME": "ALPHA MEADOWS NORTH", "AREAID": 8.0, "STR12M": 0.0, "CLS12M": 0.0, "STR4M": 0.0, "CLS4M": 0.0, "TOTAL": 12.0, "OCC": 0.0, "NFU": 0.0, "UNC": 0.0, "DVL": 0.0, "UDVL": 0.0 }, "geometry": { "type": "Point", "coordinates": [ -92.839131163095786, 37.119205483765143 ] } }
]
}
When I console.log(this._retRecords); Chrome reports shows the object with all the properties I expected from the dataset:
Object
14 PARK PLACE PH 4: Array[2]
0: -93.27512816536759
1: 37.044305883435
length: 2
__proto__: Array[0]
ALPHA MEADOWS NORTH: Array[2]
0: -92.839131163095786
1: 37.119205483765143
length: 2
__proto__: Array[0]
Using both methods given on this question report 0 length.
I am quite certain I am missing something fundamental but I cannot find what it is. Any help, criticism, alternative methods would be great!

It appears that you don't understand that your getJSON() function starts immediately (e.g. sends the request) and then returns immediately long before the getJSON function has completed it's work. It's work will be done sometime later when the completion function is called. Thus retRecords is not yet populated when the _recordsFromGeoJSON() function returns.
This is asynchronous programming. The completion function for getJSON will be called sometime LATER, long after _recordsFromGeoJSON() returns. Thus, you cannot treat it like synchronous, serial programming.
Instead, retRecords is only known in the completion function or in any function you pass the data to and call from that completion function. This is how asynchronous programming works in javascript. You must initiate all further processing of the getJSON() result from the completion function. And, you can't return the result from _recordsFromGeoJSON() because the result is not yet known when that function returns. This is a different way of coding and it a bit of a pain, but it is how you have to deal with asynchronous operations in javascript.

Related

Filter Json with javascript

I'm trying to create a function that takes a date as argument that will display the data only. This is to map it with leaflet.
The time series data looks like this:
(it's in JSON)
Time - DetectorID
0 - 5
1 - 3
2 - 4
and the geoJson that the data is mapped against is as follows:
var myGeojsonData =
{
"features": [
{
"geometry": {
"coordinates": [
144.829434,
-37.825233
],
"type": "Point"
},
"properties": {
"Area": "Combined Entry MVT on Grieve Pde, West Gate Fwy North Ramps, Grieve Pde Byp Start EB between Grieve ",
"IDnumber": "DetectorID"
},
"type": "Feature"
},...etc
I am trying to take the data from the time series with the following javascript code.
function selectdata(Time,timeseriesdata) {
output = timeseries.Time["(Time)"]
return output(time)
}
I used the pandas function to transform this to Json from a dataframe.

How to display (antimeridian) vector tiles generated by geojson-vt in leaflet using L.CRS.Simple?

I have a GeoJSON simple data that i need to display on a leaflet map using L.CRS.Simple crs, because is antimeridian data, and sometimes, coordinates can be [450,389] (more than 180)
This is the very simple GeoJSON:
{
"type": "FeatureCollection",
"name": "entities",
"features": [
{
"type": "Feature",
"properties": {
"Layer": "0",
"SubClasses": "AcDbEntity:AcDbPolyline",
"EntityHandle": "1F9",
"style": "PEN(c:#FF0000)"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
0,
0
],
[
0,
150
],
[
150,
150
],
[
150,
0
],
[
0,
0
]
]
}
}
]
}
Using geojson-vt, (demo page) i'm getting this rectangle:
I made some modifications to geojson-vt lib:
Projection functions:
function projectX(x, simple, projectionFactor) {
return x / 256 + 1;
}
function projectY(y, simple, projectionFactor) {
return - y / 256 + 0.5;
}
I added to GeoJSONVT.prototype.getTile function this line:
y = y + (1 << (z - 1)); // xy map
And the result is (markers are placed on [0,0],[150,0],[150,150],[0,150]):
Any suggestion? Why i'm losing tiles here?
I recommend you read this: https://macwright.org/2016/09/26/the-180th-meridian.html
Quoting the GeoJSON spec recommended solution:
In representing Features that cross the antimeridian, interoperability is improved by modifying their geometry. Any geometry that crosses the antimeridian SHOULD be represented by cutting it in two such that neither part’s representation crosses the antimeridian. - GeoJSON Spec, 3.1.9

Accessing variables in a JSON?

I'm currently working with the Bing Isochrone Api. I set up my http request in Angular using the HTTPClient. This is the example of the data set I get back:
{
"authenticationResultCode": "ValidCredentials",
"brandLogoUri": "http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
"copyright": "Copyright © 2018 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
"resourceSets": [{
"estimatedTotal": 1,
"resources": [{
"__type": "IsochroneResponse:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1",
"origin": {
"latitude": 47.640068,
"longitude": -122.129858
},
"polygons": [{
"coordinates": [
[
[48.22848, -122.12867],
[48.22613, -122.10625],
[48.229309, -122.08228],
[48.23733, -122.07666],
[48.24474, -122.05325],
[48.24469, -122.0532],
[48.24424, -122.05386],
[48.23119, -122.06654],
[48.22848, -122.12867]
]
]
}]
}]
}],
"statusCode": 200,
"statusDescription": "OK",
"traceId": "4ed97517798141a1b5bb9df40509f190|CO30305304|7.7.0.0|"
}
I can get to the resourceSets with this
this
.http
.get(`http://dev.virtualearth.net/REST/v1/Routes/Isochrones?waypoint=\
${this.testPointlat},${this.testPointlong}&maxTime=15&timeUnit=Minutes\
&dateTime=2017-11-27T18:00:00-08:00&travelMode=Driving\
&key=$$$$$$$$$$$$$
`).subscribe(
(response) => {
this.driveTimeCoords = response.resourceSets;
console.log(this.driveTimeCoords);
const polygons = this.driveTimeCoords.resources.polygons;
console.log(polygons);
}
);
})
So this.driveTimeCoords gives me an array... My attempt after it doesn't work obviously as it says undefined. Would i do a .foreach with an if or something? I'm probably overthinking this. All I want are the coordinates so I can then .map() them into a geojson featuregroup for leaflet.
Thanks!
Edit:
On console.log this.driveTimeCoords I get
[{…}]0: estimatedTotal: 1resources: [{…}]
Your JSON formatting is off: note how resourceSets, resources and polygons are object arrays, meaning you need to call the array's index to access the data, like so:
this.driveTimeCoords = response.resourceSets[0];
console.log(this.driveTimeCoords);
const polygons = this.driveTimeCoords.resources[0].polygons[0];
console.log(polygons);
To fix this issue, your JSON should be formatted like this:
{
"authenticationResultCode": "ValidCredentials",
"brandLogoUri": "http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
"copyright": "Copyright © 2018 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
"resourceSets": {
"estimatedTotal": 1,
"resources": {
"__type": "IsochroneResponse:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1",
"origin": {
"latitude": 47.640068,
"longitude": -122.129858
},
"polygons": {
"coordinates": [
{"latitude": 48.22848, "longitude": -122.12867},
{"latitude": 48.22613, "longitude": -122.10625},
{"latitude": 48.229309, "longitude": -122.08228},
{"latitude": 48.23733, "longitude": -122.07666},
{"latitude": 48.24474, "longitude": -122.05325},
{"latitude": 48.24469, "longitude": -122.0532},
{"latitude": 48.24424, "longitude": -122.05386},
{"latitude": 48.23119, "longitude": -122.06654},
{"latitude": 48.22848, "longitude": -122.12867}
]
}
}
},
"statusCode": 200,
"statusDescription": "OK",
"traceId": "4ed97517798141a1b5bb9df40509f190|CO30305304|7.7.0.0|"
}
I added variable names to the coordinates, for easier comprehension of the data being read.
Judging by your JSON object, it looks like this.driveTimeCoords which is a reference to the resourceSets in your JSON, is an array, which, for every property you seem to want (resource, polygons, coordinates) all successively are arrays as well. Thus, you must do a sequence of nested .map() operations.
Try the following:
var result = this.driveTimeCoords.map((obj)=>{
return obj.resources.map((resource)=>{
return resource.polygon.map((poly)=> poly.coordinates )
})
})
Doing this, makes it so that, if any of those arrays contain multiple references, you'd get them all. Afterwards, you could flatten the array, or simply reference the first one as another guy suggested result[0][0][0]
Seeing as they are arrays, you need to access via thier index:
let json = {
"authenticationResultCode": "ValidCredentials",
"brandLogoUri": "http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
"copyright": "Copyright © 2018 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
"resourceSets": [{
"estimatedTotal": 1,
"resources": [{
"__type": "IsochroneResponse:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1",
"origin": {
"latitude": 47.640068,
"longitude": -122.129858
},
"polygons": [{
"coordinates": [
[
[48.22848, -122.12867],
[48.22613, -122.10625],
[48.229309, -122.08228],
[48.23733, -122.07666],
[48.24474, -122.05325],
[48.24469, -122.0532],
[48.24424, -122.05386],
[48.23119, -122.06654],
[48.22848, -122.12867]
]
]
}]
}]
}],
"statusCode": 200,
"statusDescription": "OK",
"traceId": "4ed97517798141a1b5bb9df40509f190|CO30305304|7.7.0.0|"
}
let polys = json['resourceSets'][0].resources[0].polygons;
let o = document.getElementById('output');
o.innerHTML = JSON.stringify(polys);
<div id="output"></div>
With this formating you can acces coordinate with these paths :
.resourceSets[0].resources[0].polygons[0].coordinates[0][0][0] = 48.22848
.resourceSets[0].resources[0].polygons[0].coordinates[0][0][1] = -122.12867
.resourceSets[0].resources[0].polygons[0].coordinates[0][1][0] = 48.22613
.resourceSets[0].resources[0].polygons[0].coordinates[0][1][1] = -122.10625
.resourceSets[0].resources[0].polygons[0].coordinates[0][2][0] = 48.229309
.resourceSets[0].resources[0].polygons[0].coordinates[0][2][1] = -122.08228
.resourceSets[0].resources[0].polygons[0].coordinates[0][3][0] = 48.23733
.resourceSets[0].resources[0].polygons[0].coordinates[0][3][1] = -122.07666
.resourceSets[0].resources[0].polygons[0].coordinates[0][4][0] = 48.24474
.resourceSets[0].resources[0].polygons[0].coordinates[0][4][1] = -122.05325
.resourceSets[0].resources[0].polygons[0].coordinates[0][5][0] = 48.24469
.resourceSets[0].resources[0].polygons[0].coordinates[0][5][1] = -122.0532
.resourceSets[0].resources[0].polygons[0].coordinates[0][6][0] = 48.24424
.resourceSets[0].resources[0].polygons[0].coordinates[0][6][1] = -122.05386
.resourceSets[0].resources[0].polygons[0].coordinates[0][7][0] = 48.23119
.resourceSets[0].resources[0].polygons[0].coordinates[0][7][1] = -122.06654
.resourceSets[0].resources[0].polygons[0].coordinates[0][8][0] = 48.22848
.resourceSets[0].resources[0].polygons[0].coordinates[0][8][1] = -122.12867

Please explain .each loop in Jquery

I am new to Jquery. I am calling a Struts 2 action which return a Json object.
I dont understand how actually .each function works in Jquery.
Can you please explain how can I use the variable data, in a complex json using jquery.
{
"od": {
"cwd": [
{
"batchCount": 140,
"batchId": "2121",
"countryName": "Mexico",
"processId": "210002",
"status": "F",
"timeRequired": 140
},
{
"batchCount": 140,
"batchId": "8259",
"countryName": "Japan",
"processId": "220002",
"status": "F",
"timeRequired": 140
}
],
"percentageCompleted": 100,
"remainingTime": "-104Hours -4Mins",
"successBatchCount": 0,
"totalBatchCount": 920
},
"processDateInput": "19/11/2014" }
So here is what I wanted to know that
if json data is parsed into var obj,
Can cwd be accessed by :
var cwd = result.od.cwd;
$.each(cwd, fuction(index, value)){
var batchcount = value.batchcount;
});
and likewise can we parse any json string in jquery.
Thanks and regards,
Tushar
For basic understanding , explain you with your example,
First parent object has two object , "od" and "processDateInput" you can get the values of object directly like od.percentageCompleted , od.remainingTime, processDateInput etc..
So if there is an array inside an object then you need to go for $.each or for loop ,example
$.each(od.cwd,function(index,element){
/*index will be 0 and element will have first cwd[0] value {
"batchCount": 140,
"batchId": "2121",
"countryName": "Mexico",
"processId": "210002",
"status": "F",
"timeRequired": 140
}*/
//similar to this you can get the value
var batchCount=element.batchCount;
});

how to query array with specific condition in MongoDB

here's my mongodb object example
{
"_id": ObjectId("asdklfjasdlkfjal"),
"geometry": {
"type": "Point",
"coordinates": [
-26.62375,
152.86114
]
}
},
{
"_id": ObjectId("asdklfjasdlkfjal2"),
"geometry": {
"type": "Point",
"coordinates": [
-28.62375,
123.86114
]
}
}
I have read the document here but it does not show me an option to query only the first element of the array.
I've tried the following line on MongoHub but it gives me "invalid operator: $and" msg
{"geometry.coordinates": {$and: [{$lt: -30, $gt: 151}, {$lt: -35, $gt: 151}]}}
For example, I'd like to query the elements that have the value greater than -27 as the first value of the array. So only the first example object should be pulled no matter what value the second element has in the array (or the other way around).
Also found the same question here but it was 3yrs ago so thought there should be a better way by now.
Thanks for reading my question.
Not really the same as the question you referenced. Your "coordinates" are fixed to two positions, longitude and latitude. All you really need is "dot notation":
db.collection.find({ "geometry.coordinates.0": { "$gt": -27 } })
So the 0 stands for the fist position (longitude) and you would use 1 for the second position (latitude).

Categories