Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I'm receiving data from an Angular service as follow:
{
"data": [
{
"country": "Germany",
"iso": "de",
"city": "Berlin",
"zone": "2",
},
{
"country": "Germany",
"iso": "de",
"city": "Frankfurt",
"zone": "5",
},
{
"country": "USA",
"iso": "us",
"city": "Chicago",
"zone": "18",
},
{
"country": "USA",
"iso": "us",
"city": "New York",
"zone": "16",
},
{
"country": "USA",
"iso": "us",
"city": "San Francisco",
"zone": "54",
}
}
I would like to transform these data so I can use the AutoComplete PrimeNG widget which require the following data format as input:
groupedByCountry = [
{
label: 'Germany', value: 'de',
items: [
{label: 'Berlin', value: '2'},
{label: 'Frankfurt', value: '5'}
]
},
{
label: 'USA', value: 'us',
items: [
{label: 'Chicago', value: '18'},
{label: 'New York', value: '16'},
{label: 'San Francisco', value: '54'}
]
}
];
I'm not doing JavaScript on a daily basis and haven't be able to do this transformation so far. If someone could assist it would be appreciated
this should work:
let input = JSON.parse(`[
{
"country": "Germany",
"iso": "de",
"city": "Berlin",
"zone": "2"
},
{
"country": "Germany",
"iso": "de",
"city": "Frankfurt",
"zone": "5"
},
{
"country": "USA",
"iso": "us",
"city": "Chicago",
"zone": "18"
},
{
"country": "USA",
"iso": "us",
"city": "New York",
"zone": "16"
},
{
"country": "USA",
"iso": "us",
"city": "San Francisco",
"zone": "54"
}
]`)
const res = Object.values(input.reduce((acc, el)=>{
if(!acc[el.country]){
acc[el.country] = {
label: el.country,
value: el.iso,
items: [
{
label: el.city,
value: el.zone
}
]
}
} else {
acc[el.country].items.push({
label: el.city,
value: el.zone
})
}
return acc;
}, {}))
console.log(res)
in few words:
create a Map like country -> object
for each element of the array, if in the map that country already exists, then just push the new element, otherwise create it
Related
My Row-Data which I got from my MongoDB database. Now, I want to convert the below data to sunburst chart data. Can anyone help me?
These are my Input data array.
[
{
"globalId": "Chart Global",
"country": "India",
"state": "Gujarat",
"city": "Vadodara",
"mode": "traffic",
"value": 2.9
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Rajsthan",
"city": "Jaipur",
"mode": "traffic",
"value": 2.9
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "traffic",
"value": 100
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "population",
"value": 2000
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "animals",
"value": 5
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "birds",
"value": 0
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "trees",
"value": 0
}
]
I want data for the sunburst Chart for highcharts library
Does anyone have solutions?
As a start point you can use this function (I changed a little bit the data to see more effects):
function seqToBurstData(originalData, circleKeys){
const sunBurstData = [];
const valuePath2pointId = {}; // auxiliary data used to identify the parent id of a point
// get all the values for {dataPoint} from top key to {level} key, joined by '_'
// used to index nameLevel2pointId data, to ensure each point has a unique index value
const valuePath = (dataPoint, level) =>
Array.from({length: level}, (_, i) => dataPoint[circleKeys[i]]).join('_');
circleKeys.forEach(function(key, index){
const level = index + 1;
let currentValuePath = null, nValues = 0, sunBurstPoint;
for(const o of originalData){
const thisValuePath = valuePath(o, level);
if(thisValuePath !== currentValuePath){
currentValuePath = thisValuePath;
sunBurstPoint = {
id: level + '.' + nValues, // scheme similar to Highcharts examples for sunburst
parent: level === 1 ? null : valuePath2pointId[valuePath(o, level - 1)],
name: o[key],
level, // level not required but useful
...(level === circleKeys.length ? {value: o.value} : {}) // only for the final level
};
if(level < circleKeys.length){
valuePath2pointId[currentValuePath] = sunBurstPoint.id;
}
sunBurstData.push(sunBurstPoint);
nValues++;
}
else if(level === circleKeys.length){
sunBurstPoint.value += o.value;
}
}
});
return sunBurstData;
}
const originalData = [
{
"globalId": "Chart Global",
"first": "India",
"state": "Gujarat",
"city": "Vadodara",
"mode": "traffic",
"value": 59
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Rajasthan",
"city": "Jaipur",
"mode": "traffic",
"value": 59
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Rajasthan",
"city": "Ranthambore",
"mode": "tigers",
"value": 40
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "traffic",
"value": 100
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "population",
"value": 200
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "animals",
"value": 50
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "birds",
"value": 5
},
{
"globalId": "Chart Global",
"first": "India",
"state": "Delhi",
"city": "Delhi",
"mode": "trees",
"value": 5
}
];
const sunBurstData = seqToBurstData(originalData, ['first', 'state', 'city', 'mode']).
// add the "intro" key to change the point title according to the level
map(o=>({...o, intro: o.level === 4 ? 'The value of' : 'Total for'}));
Highcharts.chart('chart', {
chart: {
height: '100%'
},
title: {
text: ''
},
series: [{
type: 'sunburst',
data: sunBurstData,
name: sunBurstData[0].name,
allowDrillToNode: true,
cursor: 'pointer',
dataLabels: {
format: '{point.name}'
},
levels: [{
level: 1,
color: 'transparent'
}, {
level: 2,
colorByPoint: true
}, {
level: 3,
colorVariation: {
key: 'brightness',
to: 0.3
}
}, {
level: 4,
colorVariation: {
key: 'brightness',
to: -0.3
}
}]
}],
tooltip: {
headerFormat: '',
pointFormat: '{point.intro} <b>{point.name}</b> is <b>{point.value}</b>'
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/highcharts/10.3.2/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/sunburst.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<div id="chart"></div>
I'm looking to check an API response for against a set of values but the API response contains some additional info that I'm not interested in checking against
Data to check:
[
{
"address": {
"city": "London",
"firstLine": "23 High Road",
"postCode": "WC1 1AA",
"region": "South East",
"uniqueIdentifier": 239
},
"detail": {
"leaseholdFreehold": "Freehold",
"location": "Satisfactory",
"sector": "Office"
},
"valuation": {
"value": "770000",
"valuationDate": "2018-03-07",
"yield": "7.75"
}
},
{
"address": {
"city": "Leeds",
"firstLinePropertyName": "45 Headrow",
"postCode": "LS2 8AA",
"region": "North East",
"uniqueIdentifier": 287
},
"detail": {
"leaseholdFreehold": "Freehold",
"location": "Good",
"sector": "Residential"
},
"valuation": {
"value": "88000",
"valuationDate": "2018-03-07",
"yield": "8.87"
}
}
]
API response:
[
{
"address": {
"city": "London",
"firstLine": "23 High Road",
"postCode": "WC1 1AA",
"region": "South East",
"uniqueIdentifier": 239
},
"detail": {
"designAndCondition": "",
"developmentCompletionDate": "0001-01-01",
"leaseholdFreehold": "Freehold",
"location": "Satisfactory",
"sector": "Office"
},
"valuation": {
"value": "770000",
"valuationDate": "2018-03-07",
"yield": "7.75"
},
"dbIdentifier": 240
},
{
"address": {
"city": "Leeds",
"firstLinePropertyName": "11 Main Road",
"postCode": "LS2 8AA",
"region": "North East",
"uniqueIdentifier": 282
},
"detail": {
"designAndCondition": "",
"developmentCompletionDate": "0001-01-01",
"leaseholdFreehold": "Freehold",
"location": "Good",
"sector": "Residential"
},
"valuation": {
"value": "88000",
"valuationDate": "2018-03-07",
"yield": "8.75"
},
"dbIdentifier": 239
}
]
So I'm not interested in what values are returned for dbIdentifier, designAndCondition and developmentCompletionDate as they are not in my data to check against but I would like to compare the values for the rest of the properties. In practice these arrays will have more than 2 items
I was initially thinking I would remove the unwanted properties from the objects using the function below
const newArray = responseBody.map(({ dbIdentifierIdentifier, detail: { designAndCondition, developmentCompletionDate }, ...rest }) => rest)
Then ordering by address.uniqueIdentifier, converting to JSON strings and comparing the strings but the function above doesn't work with the nested properties as newArray doesn't contain the detail object at all
newArray:
[
{
"address": {
"city": "London",
"firstLine": "23 High Road",
"postCode": "WC1 1AA",
"region": "South East",
"uniqueIdentifier": 239
},
"valuation": {
"value": "770000",
"valuationDate": "2018-03-07",
"yield": "7.75"
},
"dbIdentifier": 240
},
{
"address": {
"city": "Leeds",
"firstLinePropertyName": "11 Main Road",
"postCode": "LS2 8AA",
"region": "North East",
"uniqueIdentifier": 282
},
"valuation": {
"value": "88000",
"valuationDate": "2018-03-07",
"yield": "8.75"
},
"dbIdentifier": 239
}
]
IS it possible to do it the above way by passing a destructured nested object a map function?
One way to remove the unwanted properties from the API response would be to first copy the response into a new array (to preserve the original response), then delete the properties:
const apiResponse = [{
"address": {
"city": "London",
"firstLine": "23 High Road",
"postCode": "WC1 1AA",
"region": "South East",
"uniqueIdentifier": 239
},
"detail": {
"designAndCondition": "",
"developmentCompletionDate": "0001-01-01",
"leaseholdFreehold": "Freehold",
"location": "Satisfactory",
"sector": "Office"
},
"valuation": {
"value": "770000",
"valuationDate": "2018-03-07",
"yield": "7.75"
},
"dbIdentifier": 240
},
{
"address": {
"city": "Leeds",
"firstLinePropertyName": "11 Main Road",
"postCode": "LS2 8AA",
"region": "North East",
"uniqueIdentifier": 282
},
"detail": {
"designAndCondition": "",
"developmentCompletionDate": "0001-01-01",
"leaseholdFreehold": "Freehold",
"location": "Good",
"sector": "Residential"
},
"valuation": {
"value": "88000",
"valuationDate": "2018-03-07",
"yield": "8.75"
},
"dbIdentifier": 239
}
]
let apiResponseCopy = JSON.parse(JSON.stringify(apiResponse))
var newArray = apiResponseCopy.map(i => {
delete i.dbIdentifier
delete i.detail.designAndCondition
delete i.detail.developmentCompletionDate
return i
})
console.log(newArray)
Then, you should be able to compare the newArray against your data.
I got sales data from mysql table group by state,city and product.
I used bellow query to get the data from MySql table
select state,city,product,sales from salesTable group by state,city,product;
And got bellow output from query,
[
{
"state": "S1",
"city": "CITY1",
"product": "P1",
"sales": 1000
},
{
"state": "S1",
"city": "CITY2",
"product": "P1",
"sales": 2000
},
{
"state": "S1",
"city": "CITY1",
"product": "P2",
"sales": 2000
},
{
"state": "S2",
"city": "CITY1",
"product": "P1",
"sales": 1000
},
{
"state": "S2",
"city": "CITY2",
"product": "P1",
"sales": 2000
},
{
"state": "S2",
"city": "CITY2",
"product": "P2",
"sales": 2000
},
{
"state": "S3",
"city": "CITY1",
"product": "P2",
"sales": 1000
},
{
"state": "S3",
"city": "CITY2",
"product": "P2",
"sales": 2000
}
]
Now I want to create parent child structure from dimensions=["state","city","product"]
where state is grand parent, city is parent(child of state) and product is child.
Where dimensions array should be dynamic, it might increase or decrease in length.
I need bellow output,
[
{
"sales": 5000,
"state": "S1",
"children": [
{
"sales": 3000,
"state": "S1",
"city": "CITY1",
"children": [
{
"sales": 1000,
"state": "S1",
"city": "CITY1",
"product": "P1"
},
{
"sales": 2000,
"state": "S1",
"city": "CITY1",
"product": "P2"
}
]
},
{
"sales": 2000,
"state": "S1",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S1",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S1",
"city": "CITY2",
"product": "P1"
}
]
}
]
}
]
},
{
"sales": 5000,
"state": "S2",
"children": [
{
"sales": 1000,
"state": "S2",
"city": "CITY1",
"children": [
{
"sales": 1000,
"state": "S2",
"city": "CITY1",
"product": "P1"
}
]
},
{
"sales": 4000,
"state": "S2",
"city": "CITY2",
"children": [
{
"sales": 4000,
"state": "S2",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S2",
"city": "CITY2",
"product": "P1"
},
{
"sales": 2000,
"state": "S2",
"city": "CITY2",
"product": "P2"
}
]
}
]
}
]
},
{
"sales": 3000,
"state": "S3",
"children": [
{
"sales": 1000,
"state": "S3",
"city": "CITY1",
"children": [
{
"sales": 1000,
"state": "S3",
"city": "CITY1",
"product": "P2"
}
]
},
{
"sales": 2000,
"state": "S3",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S3",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S3",
"city": "CITY2",
"product": "P2"
}
]
}
]
}
]
}
]
Maybe something like this. On the first iteration, we build the tree with temporal objects instead of arrays for easier distribution. On the second recursive iteration, we make arrays from temporal objects and calculate sales.
For unification, the topmost level also uses .children key and its .sales overall sum. This can be ignored by using result.children instead of result at the end.
const data = [
{ state: 'S1', city: 'CITY1', product: 'P1', sales: 1000 },
{ state: 'S1', city: 'CITY2', product: 'P1', sales: 2000 },
{ state: 'S1', city: 'CITY1', product: 'P2', sales: 2000 },
{ state: 'S2', city: 'CITY1', product: 'P1', sales: 1000 },
{ state: 'S2', city: 'CITY2', product: 'P1', sales: 2000 },
{ state: 'S2', city: 'CITY2', product: 'P2', sales: 2000 },
{ state: 'S3', city: 'CITY1', product: 'P2', sales: 1000 },
{ state: 'S3', city: 'CITY2', product: 'P2', sales: 2000 },
];
const dimensions = ['state', 'city', 'product'];
const childKey = dimensions[dimensions.length - 1];
const result = { children: Object.create(null) };
for (const entry of data) {
let parrent = null;
let current = result.children;
for (const dimension of dimensions) {
let slot = current[entry[dimension]];
if (!slot) {
slot = current[entry[dimension]] = Object.create(null);
slot.sales = dimension === childKey ? entry.sales : 0;
if (parrent) {
for (const [k, v] of Object.entries(parrent)) {
if (k !== 'children' && k !== 'sales') slot[k] = v;
}
}
slot[dimension] = entry[dimension];
if (dimension !== childKey) {
slot.children = Object.create(null);
}
}
parrent = slot;
current = slot.children;
}
}
normalizeAndSum(result, null);
console.log(JSON.stringify(result, null, ' '));
function normalizeAndSum(object, parent) {
if (object.children) {
object.children = Object.values(object.children);
for (const child of object.children) normalizeAndSum(child, object);
}
if (parent) {
parent.sales = parent.children.reduce((acc, { sales }) => acc + sales, 0);
}
}
I have this array of objects
[
{
"countryCode": "US",
"countryName": "United States",
"stateId": "1",
"stateName": "Alabama",
"cityId": "1",
"cityName": "Montgomery"
},
{
"countryCode": "US",
"countryName": "United States",
"stateId": "2",
"stateName": "Alabama",
"cityId": "2",
"cityName": "Birmingham"
},
{
"countryCode": "US",
"countryName": "United States",
"stateId": "2",
"stateName": "Alaska",
"cityId": "1",
"cityName": "Anchorage"
}
]
that I would like to convert to an object like the following
{
"countryCode": "US",
"countryName": "United States",
"states": [
{
"stateId": 1,
"stateName": "Alabama",
"cities": [
{
"cityId": 1,
"cityName": "Montgomery"
},
{
"cityId": 2,
"cityName": "Birmingham"
}
]
},
{
"stateId": 2,
"stateName": "Alaska",
"cities": [
{
"id": 1,
"name": "Anchorage"
}
]
}
]
}
I have tried lodash's groupBy as var grouped = _.groupBy(data, 'countryCode') but what I got is
{
HN: [
{
countryCode: 'US',
countryName: 'United States',
stateId: '1',
stateName: 'Alabama',
cityId: '1',
cityName: 'Montgomery'
},
{
countryCode: 'US',
countryName: 'United States',
stateId: '1',
stateName: 'Alabama',
cityId: '2',
cityName: 'Birmingham'
},
{
countryCode: 'US',
countryName: 'United States',
stateId: '2',
stateName: 'Alaska',
cityId: '1',
cityName: 'Anchorage'
}
]
}
I don't want the value of the property's name in which the data will be grouped by to be the key, I want the property's name being grouped by to be set as key and then create a custom property as an array to list all of the cities of a state, is there anyway to achieve this?
Thank you!
I think this is what you're looking for. This is also almost a duplicate of Javascript group objects by property
x = [{
"countryCode": "US",
"countryName": "United States",
"stateId": "1",
"stateName": "Alabama",
"cityId": "1",
"cityName": "Montgomery"
},
{
"countryCode": "US",
"countryName": "United States",
"stateId": "1",
"stateName": "Alabama",
"cityId": "2",
"cityName": "Birmingham"
},
{
"countryCode": "US",
"countryName": "United States",
"stateId": "2",
"stateName": "Alaska",
"cityId": "1",
"cityName": "Anchorage"
}
];
var stateArray = Object.values(x.reduce((result, {
countryCode,
countryName,
stateId,
stateName,
cityId,
cityName
}) => {
// Create new group
if (!result[0]) result[0] = {
countryCode,
countryName,
states: []
};
// Append to group
let state = -1;
for (let i = 0; i < result[0].states.length; i++) {
if (result[0].states[i].stateId == stateId)
state = i;
}
if (state == -1) {
result[0].states.push({
stateId,
stateName,
cities: [{
cityId,
cityName
}]
});
} else {
result[0].states[state].cities.push({
cityId,
cityName
});
}
return result;
}, {}));
console.log(stateArray)
I have a nested JSON array that getting from a mongoDB query that i would like to convert into flat JSON .I am using nested mondo documents, but i would like to show the data in a more readble way. My JSON has the following structure:
[{
"country": "Country A",
"regions": [{
"region": "region A1",
"cities": [{
"city": "city A11"
},
{
"city": "city A12"
}
]
},
{
"region": "region A2",
"cities": [{
"city": "city A21"
},
{
"city": "city A22"
}
]
}
]
},
{
"country": "Country B",
"regions": [{
"region": "region B1",
"cities": [{
"city": "city B11"
},
{
"city": "city B12"
}
]
},
{
"region": "region B2",
"cities": [{
"city": "city B21"
},
{
"city": "city B22"
}
]
}
]
}
]
I want to show only the important information and not the structure of the nested array.
How i can modify my data in Javascript on order to achieve the following result.
[
{
"country": "Country A",
"region":"Region A1",
"city": "City A11"
},
{
"country": "Country A",
"region":"Region A1",
"city": "City A12"
},
-------------
{
"country": "Country B",
"region":"Region B1",
"city": "City B11"
},
-----------
{
"country": "Country B",
"region":"Region B2",
"city": "City B22"
}
]
What is the simpliest way to acheive this result?
The simplest way is to just loop through and create an array. You can do this with reduce():
let arr = [{"country": "Country A","regions": [{"region": "region A1","cities": [{"city": "city A11"},{"city": "city A12"}]},{"region": "region A2","cities": [{"city": "city A21"},{"city": "city A22"}]}]},{"country": "Country B","regions": [{"region": "region B1","cities": [{"city": "city B11"},{"city": "city B12"}]},{"region": "region B2","cities": [{"city": "city B21"},{"city": "city B22"}]}]}]
let flat = arr.reduce((arr, {country, regions}) => {
regions.forEach(({region, cities}) => {
cities.forEach(({city}) => {
arr.push({country, region, city})
})
})
return arr
}, [])
console.log(flat)