For Each loop ---> For loop - javascript

I am having a error that states that data.forEach is not a function. The code is:
function getProperGeojsonFormat(data) {
isoGeojson = {"type": "FeatureCollection", "features": []};
console.log("After getProperGeojsonFormat function")
console.log(data)
console.log("")
data.forEach(function(element, index) {
isoGeojson.features[index] = {};
isoGeojson.features[index].type = 'Feature';
isoGeojson.features[index].properties = element.properties;
isoGeojson.features[index].geometry = {};
isoGeojson.features[index].geometry.coordinates = [];
isoGeojson.features[index].geometry.type = 'MultiPolygon';
element.geometry.geometries.forEach(function(el) {
isoGeojson.features[index].geometry.coordinates.push(el.coordinates);
});
});
$rootScope.$broadcast('isochrones', {isoGeom: isoGeojson});
}
The error I am getting is:
When I console log data:

data is an object. It looks like you want to loop over the features array within that object, so do:
data.features.forEach(function(element, index) {
isoGeojson.features[index] = {
type: 'Feature',
properties: element.properties,
geometry: {
type: 'MultiPolygon',
coordinates: element.coordinates.slice()
}
}
});

forEach works on arrays, not on objects. It seems here that data is an object.
Use this instead.
Object.keys(data).forEach(function(index) {
var element = data[index];
isoGeojson.features[index] = {};
isoGeojson.features[index].type = 'Feature';
isoGeojson.features[index].properties = element.properties;
isoGeojson.features[index].geometry = {};
isoGeojson.features[index].geometry.coordinates = [];
isoGeojson.features[index].geometry.type = 'MultiPolygon';
element.geometry.geometries.forEach(function(el) {
isoGeojson.features[index].geometry.coordinates.push(el.coordinates);
});
});
Object.keys creates an array from the keys of an object. You can then iterate over these keys and fetch the associated value.
This approach will work on any objects.

Related

Javascript get key of nested JSON object?

I have a json response that looks like the image below. I want to get all dates from the json and store in an array.
function buyOption(){
var ticker = document.getElementById('ticker').value;
fetch("https://stock-and-options-trading-data-provider.p.rapidapi.com/options/JPM", {
.then(response => response.json())
.then(data => {
dataset = data;
console.log(dataset['options'])
loadTable()
})
.catch(err => {
console.log(err);
});
function loadTable(){
expiration_dates = []
dates = dataset['options']
// console.log(JSON.parse(dates))
var keys = [];
for(var k in dates) keys.push(k);
console.log(keys)// returns ["0","1","2",3","5",6","9","10","11"]
console.log(dates[0].value) // returns undefined
}
}
goal is to have expiration_dates = ["2020-08-21","2020-08-28"]
You can try this. This will give you only the expiration dates.
var obj = {
"options": [{
"10-2-2001": "",
"someOtherProp": ""
}, {
"20-2-2001": "",
"someOtherProp": ""
}]
}
var expDates = obj.options.map(o=>Object.keys(o)[0])
console.log(expDates)
Refs:
Array.map()
Object.keys()
Try this
let result = dataSet.options.map(x => Object.keys(x));
console.log(result.flat(1))
A simple array map should do the trick and use Object.keys() array to get first key from each object in your data array
const dates = dataset['options'].map(o => Object.keys(o)[0])
console.log(dates)
<script>
const dataset = {
options: [{
'2013-12-22': {
puts: [],
calls: []
}},
{'2013-02-15': {
puts: [],
calls: []
}},
{ '2018-01-01': {
puts: [],
calls: []
}}
]
}
</script>
Something like
const options=dates.options.map(o=>
Object.keys(o).filter(k=>k.match(/^2\d{3}-\d{2}-\d{2}$/))[0]);
The idea is to loop over all options, get all keys for each of the objects and filter out the keys matching the Regexp, which is a date format, starting with 2. From the filtered keys-array I am only interested in the first element ([0]).
for(k in dates) {
keys.push((v=>{
for(let i in v) return i;
})(dates[k]));
}
Try it

Javascript push array inside object

How do I create the data array from my second api call result into the format I want?
I have a code like this
var github = require('octonode');
var client = github.client();
var userName = "octocat";
var repoName = "";
var branchName = "";
var data = [];
var branches = [];
client.get('/users/'+userName+'/repos', {}, function (err, status, body, headers) {
body.forEach(function(obj) {
repoName = obj.name;
//==============================
client.get('repos/'+userName+'/'+repoName+'/branches', {}, function (errx, statusx, bodyChild, headersx) {
bodyChild.forEach(function(objChild) {
branchName = objChild.name;
});
});
});
});
I have received repoName and branchName data as well.
I want my data format like
How to use
data.push({
name: repoName,
branches: 'branchName loooping here for every repoName'
});
so branches repetition data can be contained in my branches tag
Thank you
I guess you can do something like this:
var data = [];
client.get('/users/'+userName+'/repos', {}, function (err, status, body, headers) {
body.forEach(function(obj) {
repoName = obj.name;
client.get('repos/'+userName+'/'+repoName+'/branches', {}, function (errx, statusx, bodyChild, headersx) {
let elem = {"name": repoName, "branches": []}; //create json object for each repo
bodyChild.forEach(function(objChild) {
elem.branches.push(objChild.name); //push all branchs to that elem
});
data.push(elem); // add the elem to the data array
});
});
});
So in this case data is an object, that has a property name which is string, and another property branches which is array. If you want to push data to the property branches you can just call the push() function on it.
Please check the example below:
let data = {
name: "repoName",
branches: [
{
name: "foo"
}
]
}
data.branches.push(
{
name: "bar"
}
);
console.log(data);

Filling an array in a component with JSON objects Angular 2

I am trying to access keys and values in a JSON response to fill an array. This array is currently blank and is used for chart.js. The API: https://api.coindesk.com/v1/bpi/historical/close.json has keys and values that are changing every 24 hours, i.e.:
{"bpi":
{"2017-10-06":4370.245,
"2017-10-07":4437.0338,
}
}
The array 'data' needs to be filled inside the component.ts file, and not in a template or .html file
chartData = [
{ data: [], label: 'Bitcoin' },
];
To clarify, I am trying to fill the array 'data' with values such as '4370.245' which are coming from an http.get request from the above url.
Try this
chartData = [
{ data: [], label: 'Bitcoin' },
];
let arrayData = chartData[0].data;//this will return you data inside chartData
Edited as per coomment
var outputData = []
var keysArray = Object.keys(tmpObj.bpi)
for (var key in tmpObj.bpi) {
if (tmpObj.bpi.hasOwnProperty(key )) {
outputData.push(tmpObj.bpi[key])
}
}
console.log(outputData);
var tmpObj = {"bpi":
{"2017-10-06":4370.245,
"2017-10-07":4437.0338,
}
};
var outputData = []
var keysArray = Object.keys(tmpObj.bpi)
for (var key in tmpObj.bpi) {
if (tmpObj.bpi.hasOwnProperty(key )) {
outputData.push(tmpObj.bpi[key])
}
}
console.log(outputData);

Cannot read property 'concat' of undefined

to begin with, I have a multilevel of entities as in
country unit ----> customer reporting group ----> customers
each country unit has different customer reporting groups and each of the later has different customers
in the code the variable names are
cu ----> crg ---> customer
this is represented in a multilevel object called menuData:
menuData = {
cu1: {
CRG3: {
Customer1: {},
Customer5: {}
},
CRG7: {
Customer3: {},
Customer2: {},
Customer7: {}
}
},
cu4: {
CRG1: {
Customer2: {},
Customer4: {}
},
CRG3: {
Customer4: {}
}
}
};
what I wanted to do is to construct unique id for each level in a multilevel objects as well as in for example the ids for the customer units will be the same
cu1 and cu2 and so on
for the customer reporting groups the ids will consist of the cu + the crg as in
cu1+crg4
for the customer:
cu1+crg4+customer6;
what I did is a function called getIds
var getIds = function(menuData) {
var ids = {};
for (cu in menuData) {
ids[cu] = cu;
for (crg in menuData[cu]) {
if (!(ids[cu] in ids)) {
ids[cu] = {};
ids[cu][crg] = ids[cu].concat(crg);
} else ids[cu][crg] = ids[cu].concat(crg);
for (customer in menuData[cu][crg]) {
if (!ids[cu][crg]) {
ids[cu][crg] = {};
ids[cu][crg][customer] = ids[cu][crg].concat(customer);
} else ids[cu][crg][customer] = ids[cu][crg].concat(customer);
}
}
}
console.log(ids);
return ids;
};
the error I got is
Cannot read property 'concat' of undefined
what I have tried is that, because it says that it's undefined, I try to define it if its not already defined as in
if (!(ids[cu] in ids)) {
ids[cu] = {};
ids[cu][crg] = ids[cu].concat(crg);
}
if its not defined, define it and insert the value, but if its defined, only assign the value
else ids[cu][crg] = ids[cu].concat (crg );
why do I get this error? and how to get the the ids in multilevel objects ?
edit, excpected output is
ids = {
"cu1": {
"cu1+CRG3": { "cu1+CRG3+Customer1":{}, "cu1+CRG3+Customer5":{} },
"cu1+CRG7": { "cu1+CRG7+Customer3":{}, "cu1+CRG7+Customer2":{}, "cu1+CRG7+Customer7":{} }
},
"cu4": {
"cu4+CRG1": { "cu4+CRG1+Customer2":{}, "cu4+CRG1+Customer4":{} },
"cu4+CRG3": { "cu4+CRG3+Customer4":{}}
}
}
The Problem with your Code is that you are using Objects to store your data and Objects don´t have the Method "concat" only Arrays have the "concat" Method. Your Object must look like these to work:
menuData = [
"cu1": [
"CRG3": [ "Customer1":{}, "Customer5":{} ],
"CRG7": [ "Customer3":{}, "Customer2":{}, "Customer7":{} ]
],
"cu4": [
"CRG1": [ "Customer2":{}, "Customer4":{} ],
"CRG3": [ "Customer4":{}]
]
]
Here´s a reference : MDN Array.concat()
What can be confusing in JS is that an Object Property can be accessed like an Array.
Update after Expected Output was added:
okay than i think concat is not the right solution for your Problem.
Try it with something like this:
var ids = {};
var menuData = {
cu1: {
CRG3: {
Customer1: {},
Customer5: {}
},
CRG7: {
Customer3: {},
Customer2: {},
Customer7: {}
}
},
cu4: {
CRG1: {
Customer2: {},
Customer4: {}
},
CRG3: {
Customer4: {}
}
}
};
for (propKeyLevel1 in menuData){
ids[propKeyLevel1] = {};
var propLevel1 = ids[propKeyLevel1];
for(propKeyLevel2 in menuData[propKeyLevel1]){
propLevel1[propKeyLevel1+"+"+propKeyLevel2] = {};
var propLevel2 = propLevel1[propKeyLevel1+"+"+propKeyLevel2];
for(propKeyLevel3 in menuData[propKeyLevel1][propKeyLevel2]){
propLevel2[propKeyLevel1+"+"+propKeyLevel2+"+"+propKeyLevel3] = {};
}
}
}
console.log(ids);
concat is a method for for a String or an Array, here you call it on an object hence the error.
What you're trying to do is a bit unclear to me, but maybe you could try that :
ids[cu][crg] = crg;
instead of :
ids[cu][crg] = ids[cu].concat (crg );
Because that's what you seem to be trying.
I’d try it this way:
function getIds(dataIn, idsIn) {
idsIn = idsIn || [];
var dataOut = {}, idOut;
for (var idIn in dataIn) {
idsOut = idsIn.concat([idIn]);
dataOut[idsOut.join('+')] = getIds(dataIn[idIn], idsOut);
}
return dataOut;
}
Perfect use case for a recursive function passing down an array (idsOut) of the ids of the previous layers to generate the intended object keys. Pretty straight forward.

How to group Array & Objects?

I have an array with 3 Objects, however the second Object does not have an array inside the 'Data' Object.
I need to do an ng-repeat for each 'Artist' in the correct order, however the second object is causing issues. How would I combine each Object together?
In my Factory, I set up a call to receive three response from three different API. I set a promise for each one so they come in a the exact order I call them.
FACTORY
.factory('timeline', function($http, $q) {
var promise1 = $http({
method: "GET",
url: "http://api.example.com/last/3/?limit=3"
});
var promise2 = $http({
method: "GET",
url: "http://api.example.com/current/3/"
});
var promise3 = $http({
method: "GET",
url: "http://api.example.com/next/3/?limit=3"
});
return {
data: $q.all([promise1, promise2, promise3])
}
})
In my controller, I get the response like so.
[
Object
config
data: [Array 3]
-0: Object
artist : 'Artist'
title : 'Title'
-1: Object
-2: Object
,
Object
config
data: Object
artist : 'Artist'
title : 'Title
,
Object
config
data: [Array 3]
-0: Object
artist : 'Artist'
title : 'Title'
-1: Object
-2: Object
]
CONTROLLER
My Attempt to filter using Underscore.
.controller('StationCtrl', function($scope, $stateParams, $http, timeline) {
timeline.data.then(function(musicData) {
var row = [];
for (var i = 0; i < musicData.length; i++) {
var data = _.filter(musicData[i].data, function(x){
row.push(x);
})
}
})
})
My Goal eventually if possible would be to combine everything in order
Object
data: [Array 7]
-0: Object
-1: Object
-2: Object
-3: Object
-4: Object
-5: Object
-6: Object
,
I am still trying to figure out how to work with Objects & Arrays, any help/tips would be great.
This is a simple approach of how you can solve your problem without underscore. You just need to check whether your data is an object or an array.
var arr = [
{ data: [{ artist: 'Artist' }, { artist: 'Artist2' }]},
{ data: { artist: 'Artist3' } },
{ data: [{ artist: 'Artist4' }]}
];
var flattened = [];
arr.forEach(function (el) {
if(Array.isArray(el.data)) {
flattened = flattened.concat(el.data);
} else {
flattened.push(el.data);
}
});
See example on jsbin.
Ideally, I think you should send an array only for 2nd object with its length as 1. If the API is not in your control i.e. 3rd party or anything else then we can look forward to solve the issue in other way.
You could strip out the underscore and just do a nested for:
.controller('StationCtrl', function($scope, $stateParams, $http, timeline) {
timeline.data.then(function(musicData) {
var row = [];
var dataElement;
var i;
var j;
for (i = 0; i < musicData.length; i++) {
dataElement = musicData[i].data;
if(typeof dataElement === 'object') {
row.push(dataElement)
} else if(typeof dataElement === 'array') {
for(j = 0; j < dataElement.length; j++) {
row.push(dataElement[j]);
}
}
}
})
})

Categories

Resources