I have to extract specific data from an object. My code works but I wonder if I could improve it by using method like map or filter.
This is for no specific background just for personnel training. Also I am using Lodash library
function extractApi(data) {
var arrayOfTowns = [];
var arrayOfCityCode = [];
var result = [];
//looping throw the expected datas (cities and postcode)
for (var i = 0; i < data.features.length; i++) {
arrayOfCityCode.push(_.toString(data.features[i].properties.postcode));
arrayOfTowns.push(_.toString(data.features[i].properties.city));
//verify unique cities
arrayOfTowns = _.uniq(arrayOfTowns);
//pushing to a new array to have the expected result format
if (arrayOfTowns[i] != undefined && arrayOfCityCode != undefined){
result[i] = arrayOfCityCode[i] + " " + arrayOfTowns[i]
}
}
return result
}
//example with some datas
extractApi( {
"type": "FeatureCollection",
"limit": 20,
"version": "draft",
"licence": "ODbL 1.0",
"attribution": "BAN",
"features": [
{
"type": "Feature",
"properties": {
"importance": 0.6466,
"type": "municipality",
"adm_weight": 4,
"postcode": "43000",
"context": "43, Haute-Loire, Auvergne-Rhône-Alpes (Auvergne)",
"id": "43157",
"population": 18.8,
"x": 769600,
"y": 6438600,
"name": "Le Puy-en-Velay",
"citycode": "43157",
"label": "Le Puy-en-Velay",
"city": "Le Puy-en-Velay",
"score": 0.8769636363636364
},
"geometry": {
"coordinates": [
3.883955,
45.043141
],
"type": "Point"
}
},
{
"type": "Feature",
"properties": {
"importance": 0.0867,
"type": "municipality",
"adm_weight": 1,
"postcode": "43000",
"context": "43, Haute-Loire, Auvergne-Rhône-Alpes (Auvergne)",
"id": "43089",
"population": 3.6,
"x": 767600,
"y": 6438900,
"name": "Espaly-Saint-Marcel",
"citycode": "43089",
"label": "Espaly-Saint-Marcel",
"city": "Espaly-Saint-Marcel",
"score": 0.8260636363636362
},
"geometry": {
"coordinates": [
3.858597,
45.046041
],
"type": "Point"
}
},
],
"query": "43000"
}
)
The goal is to receive all data.features.properties.postcode and data.features.properties.city and push it to an array. For this example the expected result is ["43000 Le Puy-en-Velay", "43000 Espaly-Saint-Marcel"]. Cities in the result should be unique.
You can indeed use .map to get the results you desire:
const parsedCities = data.features
.map(f => `${f.properties.postcode} ${f.properties.city}`)
.filter((f, i, a) => a.indexOf(f) === i);
//["43000 Le Puy-en-Velay", "43000 Espaly-Saint-Marcel"]
You can find the documentation on Array.prototype.map() here.
One may use
Array.prototype.map() to extract necessary properties (citycode, city) into the string
Set to get rid of duplicates
const src = {"type":"FeatureCollection","limit":20,"version":"draft","licence":"ODbL 1.0","attribution":"BAN","features":[{"type":"Feature","properties":{"importance":0.6466,"type":"municipality","adm_weight":4,"postcode":"43000","context":"43, Haute-Loire, Auvergne-Rhône-Alpes (Auvergne)","id":"43157","population":18.8,"x":769600,"y":6438600,"name":"Le Puy-en-Velay","citycode":"43157","label":"Le Puy-en-Velay","city":"Le Puy-en-Velay","score":0.8769636363636364},"geometry":{"coordinates":[3.883955,45.043141],"type":"Point"}},{"type":"Feature","properties":{"importance":0.0867,"type":"municipality","adm_weight":1,"postcode":"43000","context":"43, Haute-Loire, Auvergne-Rhône-Alpes (Auvergne)","id":"43089","population":3.6,"x":767600,"y":6438900,"name":"Espaly-Saint-Marcel","citycode":"43089","label":"Espaly-Saint-Marcel","city":"Espaly-Saint-Marcel","score":0.8260636363636362},"geometry":{"coordinates":[3.858597,45.046041],"type":"Point"}},],"query":"43000"};
const uniqueCities = obj =>
[...new Set(obj.features.map(({properties:{city,citycode}}) => citycode+' '+city))]
console.log(uniqueCities(src));
.as-console-wrapper {min-height: 100%}
Related
How to use filter or forEach in javascript to output only the objects whithout parentId and the objects with only the first level of parentId.
Should output objects with ids: 1681, 1682, and 1683.
Should not output objects with ids: 1685, 1686 and 1687.
array = [ {
"id": 1681,
"label": "1",
"url": "page1",
},
{
"id": 1682,
"label": "2",
"url": "page1",
},
{
"id": 1683,
"label": "a",
"url": "page1",
"parentId": 1681,
},
{
"id": 1685,
"label": "aa",
"url": "page1",
"parentId": 1683,
},
{
"id": 1686,
"label": "aaa",
"url": "page1",
"parentId": 1683,
},
{
"id": 1687,
"label": "aaaa",
"url": "page1",
"parentId": 1683,
}
]
Something like this...
array.filter(({item}) => !item.parentId ? item.id : item.parentId)
We have to save the information if we already found a parentId from inside the filter function. A handy way to do this is by using the prefix operator ++ on a counter. This way we get around an explicit, long assignment with =. Instead we make it before.
Additionally with destructuring assignment we can extract the parentId comfortably of the array items and write a really short filter:
array=[{id:1681,label:"1",url:"page1"},{id:1682,label:"2",url:"page1"},{id:1683,label:"a",url:"page1",parentId:1681},{id:1685,label:"aa",url:"page1",parentId:1683},{id:1686,label:"aaa",url:"page1",parentId:1683},{id:1687,label:"aaaa",url:"page1",parentId:1683}];
window.parentIdCount = 0;
window.filtered =
array.filter(({parentId}) => !parentId || ++parentIdCount <= 1)
console.log(filtered)
Something like this ought to work:
const result = array.filter(object => object.parentId === undefined);
I am trying to define a "complex" object:
var tM = JSON.parse('{"version":"","series":[{"name":"","possModes":[],"instance":[{"date":"","mode":""}]}]}');
where all items of array "instance" should be objects of type
{"date":"","mode":""}
and all items of array "series" should be objects of type
{"name":"","possModes":[],"instance":[{"date":"","mode":""}]}
The problem is that only the items of index [0] are getting the proper properties and items of higher indexes are "undefined", so I cannot set them to their needed values.
I have also tried to define tM explicitly, like:
var Cinstance = new Object();
Cinstance.date = "";
Cinstance.mode = "";
var Cseries = new Object();
Cseries.name = '';
Cseries.possModes = [];
Cseries.instance = [new Object(Cinstance)];
var tM= new Object();
tM.version = "";
tM.series = [new Object(Cseries)];
and also like:
var tM = {series:
[{instance:
[{date:"",mode:""}
]
}
]
}
(this is a version reduced to my specific problem).
Of course, they both end up with the same result - only items of index [0] are defined.
The data structure provided by the OP ...
{
"version": "",
"series": [{
"name": "",
"possModes": [],
"instance": [{
"date": "",
"mode": ""
}]
}]
}
... does validate against the following JSON schema ...
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "My-Special-Schema-Or-Data-Structure-Title",
"description": "Whatever I have to say about my described structure",
"type": "object",
"properties": {
"version": {
"description": " ... ",
"type": "string"
},
"series": {
"description": " ... ",
"type": "array",
"minItems": 1,
"items": {
"description": " ... ",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"possModes": {
"description": " ... ",
"type": "array"
},
"instance": {
"description": " ... ",
"type": "array",
"minItems": 1,
"items": {
"description": " ... ",
"type": "object",
"properties": {
"date": {
"type": "string"
},
"mode": {
"type": "string"
}
},
"required": [
"date",
"mode"
]
}
}
},
"required": [
"name",
"possModes",
"instance"
]
}
}
},
"required": [
"version",
"series"
]
}
There is even a JSON Schema Generator one could start with. Passing the OP's originally provided data structure, one gets a solid base of a JSON Schema, one then can continue tailoring.
I have a JSON object like this, I wanna access the list array elements with key and value in postman.
{
"data": {
"total": 1,
"list": [
{
"id": 53,
"name": "Sonu",
"mobileNo": "6543213456",
"address": "Greeny Pathway",
"city": "NewYork",
"mode": "Weekly",
"duration": "15",
"qty": null
}
]
},
"success": true,
"message": ""
}
How to separate it as Key and Value in Javascript like,
Key: id,name,mobileNo,address,city,..
Value: 53,Sonu,6543213456,Greeny Pathway,NewYork,....
First remove comma from line : "qty": null, otherwise it will cause error in json parsing.
var resultJSON = `{
"data": {
"total": 1,
"list": [
{
"id": 53,
"name": "Sonu",
"mobileNo": "6543213456",
"address": "Greeny Pathway",
"city": "NewYork",
"mode": "Weekly",
"duration": "15",
"qty": null
}
]
},
"success": true,
"message": ""
}`;
var result = $.parseJSON(resultJSON);
var myList = result.data.list[0];
$.each(myList, function(k, v) {
//display the key and value pair
alert(k + ' is ' + v);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
you can use below codes:
const keys = Object.keys(jsonObject);
const values = Object.values(jsonObject);
But your JSON object is deep, you should flatten it and then use keys and values of Object to make them separate.
You can get using key and value separately in a array.
var a = {
"data": {
"total": 1,
"list": [
{
"id": 53,
"name": "Sonu",
"mobileNo": "6543213456",
"address": "Greeny Pathway",
"city": "NewYork",
"mode": "Weekly",
"duration": "15",
"qty": null,
}
]
},
"success": true,
"message": ""
}
var keyval = Object.keys(a.data.list[0])
console.log(keyval)
var values = Object.values(a.data.list[0])
console.log(values)
JSON objects are key value pair you cannot get the keys and values in object form as you desire but you can get both in form of arrays from this code
var key = []
var values = []
list.map(function(l){ keys = Object.getOwnPropertyNames(l);
keys.map(function(key) {values.push(l[key]);})})
Finally this works for me!(In Postman Script)
var resdata = JSON.parse(responseBody);
console.log(resdata);
key = Object.keys(resdata.data.list[0]);
console.log(key);
value =Object.values(resdata.data.list[0]);
console.log(value);
I have a web app which passes delimited fields to another web page. It works fine! But... I want to list the fields (Name) that don't exist in the javascript object. How can this be accomplished?
JS object:
var members = [ { "Class": "E", "Rating": "1000", "ID": "16720664", "Name": "Adeyemon, Murie", "Expires": "1000.10.10" },
{ "Class": "B", "Rating": "1735", "ID": "12537964", "Name": "Ahmed, Jamshed", "Expires": "2018.10.18" },
{ "Class": "C", "Rating": "1535", "ID": "12210580", "Name": "Attaya, James", "Expires": "2019.01.12" },
{ "Class": "F", "Rating": "0001", "ID": "16281977", "Name": "Auld, Thomas", "Expires": "1000.10.10" },
{ "Class": "B", "Rating": "1793", "ID": "10117780", "Name": "Badamo, Anthony", "Expires": "2018.09.12" }
]
JS CODE:
let dataString = "Adeyemon, Murie|Ahmed, Jamshed|Attaya, James|Badamo, Anthony|Birmingham, Gerald|";
let splitString = dataString.split("|");
for (let i = 0; i < splitString.length; i++) {
$temp = splitString[i - 1];
if ($temp > "") {
members.find(x => x.Name === $temp);
}
}
use filter
var dataString =
'Adeyemon, Murie|Ahmed, Jamshed|Attaya, James|Badamo, Anthony|Birmingham, Gerald|'
var members = [{"Class":"E","Rating":"1000","ID":"16720664","Name":"Adeyemon, Murie","Expires":"1000.10.10"},{"Class":"B","Rating":"1735","ID":"12537964","Name":"Ahmed, Jamshed","Expires":"2018.10.18"},{"Class":"C","Rating":"1535","ID":"12210580","Name":"Attaya, James","Expires":"2019.01.12"},{"Class":"F","Rating":"0001","ID":"16281977","Name":"Auld, Thomas","Expires":"1000.10.10"},{"Class":"B","Rating":"1793","ID":"10117780","Name":"Badamo, Anthony","Expires":"2018.09.12"}]
var res = dataString.split('|').filter(
name => !members.map(o => o.Name).find(n => n === name)
).filter(name=>name.trim()!=='')
console.log(res);
You can first create Name to object mapping and then search name from string in this object/map which will cost O(n) for n names.
var members = [ { "Class": "E", "Rating": "1000", "ID": "16720664", "Name": "Adeyemon, Murie", "Expires": "1000.10.10" },
{ "Class": "B", "Rating": "1735", "ID": "12537964", "Name": "Ahmed, Jamshed", "Expires": "2018.10.18" },
{ "Class": "C", "Rating": "1535", "ID": "12210580", "Name": "Attaya, James", "Expires": "2019.01.12" },
{ "Class": "F", "Rating": "0001", "ID": "16281977", "Name": "Auld, Thomas", "Expires": "1000.10.10" },
{ "Class": "B", "Rating": "1793", "ID": "10117780", "Name": "Badamo, Anthony", "Expires": "2018.09.12" }
];
var nameMap = members.reduce((prev, next) => {
prev[next.Name] = next;
return prev;
}, {});
let dataString = "Adeyemon, Murie|Ahmed, Jamshed|Attaya, James|Badamo, Anthony|Birmingham, Gerald|";
let names = dataString.split("|");
let result = names.filter(name => name && !(name in nameMap));
console.log(result);
Try reducing the members array to a Set of names. Then you can filter your splitString array using Set.prototype.has()
const members = [{"Class":"E","Rating":"1000","ID":"16720664","Name":"Adeyemon, Murie","Expires":"1000.10.10"},{"Class":"B","Rating":"1735","ID":"12537964","Name":"Ahmed, Jamshed","Expires":"2018.10.18"},{"Class":"C","Rating":"1535","ID":"12210580","Name":"Attaya, James","Expires":"2019.01.12"},{"Class":"F","Rating":"0001","ID":"16281977","Name":"Auld, Thomas","Expires":"1000.10.10"},{"Class":"B","Rating":"1793","ID":"10117780","Name":"Badamo, Anthony","Expires":"2018.09.12"}]
const dataString = "Adeyemon, Murie|Ahmed, Jamshed|Attaya, James|Badamo, Anthony|Birmingham, Gerald|";
const names = members.reduce((c, {Name}) => c.add(Name), new Set())
const missing = dataString.split('|')
.filter(name => name.trim() && !names.has(name))
.join('; ') // output from your comment on another answer
console.info(missing)
I've added in the name.trim() to filter out the empty record created by the trailing | in your dataString.
The reason for creating a Set is to avoid searching the entire members array for each name in dataString. Set.prototype.has() should be O(1)
Fiddle Example
I want to convert this JSON data
var data = [
{
"computer": 24,
"brand": "Italy A",
"phone": 0,
"country": "Italy"
},
{
"brand": "Italy C",
"computer": 0,
"phone": 0,
"country": "Italy"
},
{
"brand": "Brazil B",
"computer": 0,
"phone": 22,
"country": "Brazil"
},
{
"computer": 0,
"brand": "Brazil D",
"phone": 62,
"country": "Brazil"
},
{
"computer": 34,
"brand": "US E",
"phone": 41,
"country": "US"
}
];
into a hierarchical form for a d3 graph:
{
"name": "categories",
"children": [
{
"name": "phone",
"children": [
{
"name": "US",
"children": [
{
"brand": "US E",
"size": 41
}
]
},
{
"name": "Brazil",
"children": [
{
"brand": "Brazil B",
"size": 22
},
{
"brand": "Brazil D",
"size": 62
}
]
},
{
"name": "Italy",
"children": []
}
]
},
{
"name": "computer",
"children": [
{
"name": "US",
"children": [
{
"brand": "US E",
"size": 34
}
]
},
{
"name": "Brazil",
"children": []
},
{
"name": "Italy",
"children": [
{
"brand": "Italy A",
"size": 24
}
]
}
]
}
]
}
I came up with this code to generate the format:
function group_children(data){
var categories = ["phone","computer"];
var countries = ["US","Brazil","Italy"];
var object = {name:"categories",children:[]};
for(var c =0; c < categories.length;c++){
object.children.push({"name":categories[c],children:[]});
for(var con = 0;con < countries.length;con++){
object.children[c].children.push({"name":countries[con],"children":[]});
}
}
for(var i = 0;i < data.length;i++){
var row = data[i];
for(var c =0; c < categories.length;c++){
for(var con = 0;con < countries.length;con++){
var cat_key = categories[c],
country_key = countries[con];
if(row[cat_key] > 0){
if(object.children[c].name == cat_key && row.country == country_key){ object.children[c].children[con].children.push({brand:row["brand"],size:row[cat_key]});
}
}
}
}
}
return object;
}
Is it possible , during the iteration, not to push a country into the brand or computer's children array if the country's children array is empty?
For example, these objects should be removed
// computer
{
"name": "Brazil",
"children": []
}
// phone:
{
"name": "Italy",
"children": []
}
Here's the part that push each country into each category's children array:
for(var c =0; c < categories.length;c++){
object.children.push({"name":categories[c],children:[]});
for(var con = 0;con < countries.length;con++){
object.children[c].children.push({"name":countries[con],"children":[]});
}
}
My approach is probably wrong, so any other suggestions converting the data into that hierarchical form is also appreciated.
Check this fiddle, is this what you're looking for? I decided to go for a different approach to the one you followed, hope you don't mind. I've commented the code so that it's clearer:
var result = {
name: "categories",
children: [{
"name": "phone",
"children": []
}, {
"name": "computer",
"children": []
}]
};
$.each(data, function (index, item) {// Go through data and populate the result object.
if (+item.computer > 0) { // Computer has items.
filterAndAdd(item, result.children[1], "computer");
}
if (+item.phone > 0) { // Phone has items.
filterAndAdd(item, result.children[0], "phone");
}
});
function filterAndAdd(item, result_place, type) {// Search and populate.
var i = -1;
$.each(result_place.children, function (index,a) {
if( a.name === item.country ) {
i = index;
return false;
}
});
if (i > -1) {// Country already exists, add to children array.
result_place.children[i].children.push({
"brand": item.brand,
"size": item[type]
});
} else {// Country doesn't exist, create it.
result_place.children.push({
"name": item.country,
"children": [{
"brand": item.brand,
"size": item[type]
}]
});
}
}
Hope it helps.
You have to use d3.nest() function to group array elements hierarchically. The documentation is available
here. Also go through this tutorial which could definitely help you to create hierarchical data.
That's not enough, you get hierarchical data in terms of key and value pairs. But if you want to convert into name and children, already a question on SO is asked, check this.
With your current approach you should iterate the data to find the empty ones, before pushing the countries, which would result in way more iteration than just simply iterating the result at the end to filter the empty ones.
Otherwise you should create the scruture in the same iterations of the data insertion, thus reducing the iterations to 1.