How to fomat nested Json using Vanilla Js - javascript

I want to transform the Input JSON to Output Array of Objects, Use Input JSON array and use only vanilla Javascript, loop through JSON object. I tried foreach function but faced some issues. print output like given below
let Input ={
details:[
{
"id":"Country_name",
"values":[
"India",
"England",
"Germany"
]
},
{
"id":"Country_capital",
"values":[
"Delhi",
"London",
"Berlin"
]
}
],
metadata:[
{
"id":"Country_name",
"label":"Country"
},
{
"id":"Country_capital",
"label":"Capital"
}
]
}
let Output =[
{
"Country":"India",
"Capital":"Delhi"
},
{
"Country":"England",
"Capital":"London"
},
{
"Country":"Germany",
"Capital":"Berlin"
}
]
Object.keys(input).forEach(function(value, key) {
input[value].forEach(function(v, k) {
console.log(v.id)
})
})

You can try something like this
const input = {
details: [{
"id": "Country_name",
"values": [
"India",
"England",
"Germany"
]
},
{
"id": "Country_capital",
"values": [
"Delhi",
"London",
"Berlin"
]
}
],
metadata: [{
"id": "Country_name",
"label": "Country"
},
{
"id": "Country_capital",
"label": "Capital"
}
]
};
function transform(input) {
const ids = {};
for (const detail of input.details) {
ids[detail.id] = detail.values;
}
const meta = {};
for (const m of input.metadata) {
meta[m.id] = m.label;
}
const idsKeys = Object.keys(ids);
const out = [];
for (let i = 0; i < ids[idsKeys[0]].length; i++) {
const obj = {};
for (const key of idsKeys) {
obj[meta[key]] = ids[key][i];
}
out.push(obj);
}
return out;
}
console.log(transform(input));

I changed the input and the variable in the top
This may work for you or not
let input ={
details:[
{
"id":"Country_name",
"values":[
"India",
"England",
"Germany"
]
},
{
"id":"Country_capital",
"values":[
"Delhi",
"London",
"Berlin"
]
}
],
metadata:[
{
"id":"Country_name",
"label":"Country"
},
{
"id":"Country_capital",
"label":"Capital"
}
]
}
let Output =[
{
"Country":"India",
"Capital":"Delhi"
},
{
"Country":"England",
"Capital":"London"
},
{
"Country":"Germany",
"Capital":"Berlin"
}
]
Object.keys(input).forEach(function(value, key) {
input[value].forEach(function(v, k) {
console.log(v.id)
})
})
If you have anymore questions or problems I would be happy to help

Countries are in Input.details[0].values
Capitals are in Input.details[1].values
Just make an object containing country on one go through countries, then add capital to each one on second pass through capitals
let Input = {
details: [{
"id": "Country_name",
"values": [
"India",
"England",
"Germany"
]
},
{
"id": "Country_capital",
"values": [
"Delhi",
"London",
"Berlin"
]
}
],
metadata: [{
"id": "Country_name",
"label": "Country"
},
{
"id": "Country_capital",
"label": "Capital"
}
]
};
let Output = [{
"Country": "India",
"Capital": "Delhi"
},
{
"Country": "England",
"Capital": "London"
},
{
"Country": "Germany",
"Capital": "Berlin"
}
];
const newOutput = [];
const countries = Input.details[0].values;
countries.forEach(country => {
console.log(country);
newOutput.push({"Country": country});
});
const capitals = Input.details[1].values;
capitals.forEach((capital, i) => {
console.log(capital);
newOutput[i]["Capital"] = capital;
});
console.log(newOutput);

a shorthand method to do this is mapping the data arrays of input :
let input ={
details:[
{
"id":"Country_name",
"values":[
"India",
"England",
"Germany"
]
},
{
"id":"Country_capital",
"values":[
"Delhi",
"London",
"Berlin"
]
}
],
metadata:[
{
"id":"Country_name",
"label":"Country"
},
{
"id":"Country_capital",
"label":"Capital"
}
]
}
let Output =[
{
"Country":"India",
"Capital":"Delhi"
},
{
"Country":"England",
"Capital":"London"
},
{
"Country":"Germany",
"Capital":"Berlin"
}
]
let data = input.details
let countries = data[0].values
let capitals = data[1].values
const output = countries.map((el, index) => ({"country": el, "capital": capitals[index]}))
console.log(output)
However, in your code, you are referring to Input object as input , which are two different variables

Related

How to filter children JSON objects based on some value Angular 8

I am getting API response inside filterchildrenByRegion() function,
I want to remove those object which are not matching with the selected Region and return all data as it is.
Ex 1 - If i will pass '1UL Africa' inside changeRegion() function,than it will return data as my expected output 1.
Ex - 2 - If i will pass 'South Africa"' inside changeRegion() function,than it will return data as my expected output 2.
changeRegion(){
this.newRegion = this.filterchildrenByRegion('1UL Africa');
}
filterchildrenByRegion(region){
this.data = [
{
"name": "Africa",
"children": [
{
"name": "Test1",
"region": "1UL Africa"
},
{
"name": "Test2",
"region": "South Africa",
},
{
"name": "Test3",
"region": "New Test",
}
]
},
{
"name": "Europe",
"children": [
{
"name": "Test4",
"region": "1UL Africa"
},
{
"name": "Test5",
"region": "Test Europe"
}
]
}
];
return this.data.filter(x => x.children.map(child => child.region).includes(regionName));
};
Expected Output 1
result = [
{
"name": "Africa",
"children": [
{
"name": "Test1",
"region": "1UL Africa"
}
]
},
{
"name": "Europe",
"children": [
{
"name": "Test4",
"region": "1UL Africa"
}
]
}
];
I tried below code but it is returning empty result to me
getClusterObjectByRegion(regionName: string) {
this.data = this.clusterFactoryList;
return this.data.map((x) => {
const childrenFulfillingTheSearch = x.children.filter(c => c.buSubRegion.includes(regionName));
if (childrenFulfillingTheSearch.length === 0) {
return undefined;
}
return {
...x,
children: childrenFulfillingTheSearch
};
}).filter(x => x !== undefined);
};
Expected Output 2
result = [
{
"name": "Africa",
"children": [
{
"name": "Test1",
"region": "1UL Africa"
}
]
}
];
Maybe not the most efficient, but it works, if I understood your needs correctly:
function getByRegion(region: string) {
return data.map(r => ({...r, children: r.children.filter(c => c.region === region)}))
.filter(r => r.children.length > 0);
}

How to filter from an object by iterating over it in js

I am trying to get the value of "type" from the object by iterating over it. The object looks like this.
{
"team": {
"table": [
{
"cityCode": 123,
"list": {
"players": [
{
"name": "peter",
"school": "x",
"awards": {
"type": "gold"
},
"year": 2019
}
]
}
},
{
"cityCode": 456,
"list": {
"players": [
{
"name": "Dave",
"school": "y",
"awards": {
"type": "silver"
},
"year": 2018
}
]
}
}
]
}
}
I am able to get the type values using this:
const table = team.table;
for (let i = 0; i < table.length; i++) {
const values = {
type: table[i].list.players
.filter((a) => a.awards != null)
.map((a) => a.awards.type)
.join(" "),
};
}
However, I want to use another filter on the "list" to filter non null lists. So how can I achieve that.
You want to check Check if 'list' key exists inside a team.table JSON object
you can check by
if(table[i].hasOwnProperty('list')){
}
code is
const table = team.table;
for (let i = 0; i < table.length; i++) {
if(table[i].hasOwnProperty('list')){
const values = {
type: table[i].list.players
.filter((a) => a.awards != null)
.map((a) => a.awards.type)
.join(" "),
};
}
}
1) You can get all type using flatMap and map as:
obj.team.table.flatMap((o) => o.list.players.map((o) => o.awards.type))
const obj = {
team: {
table: [
{
cityCode: 123,
list: {
players: [
{
name: "peter",
school: "x",
awards: {
type: "gold",
},
year: 2019,
},
],
},
},
{
cityCode: 456,
list: {
players: [
{
name: "Dave",
school: "y",
awards: {
type: "silver",
},
year: 2018,
},
],
},
},
],
},
};
const types = obj.team.table.flatMap((o) => o.list.players.map((o) => o.awards.type));
console.log(types);
2) Using forEach and destructuring as:
const obj = {
team: {
table: [
{
cityCode: 123,
list: {
players: [
{
name: "peter",
school: "x",
awards: {
type: "gold",
},
year: 2019,
},
],
},
},
{
cityCode: 456,
list: {
players: [
{
name: "Dave",
school: "y",
awards: {
type: "silver",
},
year: 2018,
},
],
},
},
],
},
};
const table = obj.team.table;
const types = [];
for (let i = 0; i < table.length; i++) {
const { list: { players } } = table[i]
players.forEach(({ awards: { type }}) => types.push(type))
}
console.log(types);
It will be cleaner to use forEach.
You will need 2 forEach due to your data structure.
But below code will:
check if awards is null
check if awards.type is null
const data = {
"team": {
"table": [
{
"cityCode": 123,
"list": {
"players": [
{
"name": "peter",
"school": "x",
"awards": {
"type": "gold"
},
"year": 2019
}
]
}
},
{
"cityCode": 456,
"list": {
"players": [
{
"name": "Dave",
"school": "y",
"awards": {
"type": "silver"
},
"year": 2018
},
{
"name": "Dave",
"school": "y",
"awards": {
"type": "gold"
},
"year": 2016
}
]
}
},
{
"cityCode": 444,
"list": {
"players": [
{
"name": "James",
"school": "y",
"awards": {
"type": null
},
"year": 2016
}
]
}
},
{
"cityCode": 555,
"list": {
"players": [
{
"name": "Name 101",
"school": "y",
"awards": {
"type": "platinum"
},
"year": 2016
},
{
"name": "Name 102",
"school": "y",
"awards": {
"type": null
},
"year": 2016
},
{
"name": "Name 103",
"school": "y",
"awards": null,
"year": 2016
},
]
}
}
]
}
}
// Expanded your data with more items
const data1 = data.team.table;
let types = []
data1.forEach((item, index) => {
item.list.players.forEach((player) => {
const awards = player.awards;
if (awards !== null && awards.type !== null) {
types = [...types, awards.type];
}
})
})
// Get the list of types
console.log(types);
// Get unique list of types
let unique_types = [...new Set(types)]
console.log(unique_types);

Group and count the nested json response - Angular

Im trying to bind value in Angular Material table, before that i need to process the GET response v
trying to achieve like below(just for understanding)
my faulty code
let filterByLocation = data.reduce((r, { group: location.country, ...object }) => {
var finalArry = r.find(o => o.location === location);
if (!finalArry) r.push(temp = { location, locationObj: [] });
finalArry.locationObj.push(object);
return r;
}, []);
console.log(filterByLocation);
thanks to #Nishant Dixit for his working snippet
const finalResponse = data.response.reduce((r, {
location: {
country: group
},
...object
}) => {
r[group] = r[group] || {
location: group,
locationObj: []
};
r[group].locationObj.push(object);
return r;
}, {});
console.log(finalResponse)
const data = {
"totalRec": 5,
"response": [
{
"employee": {
"uid": 1,
"empName": "Jade"
},
"location": {
"country": "UK",
"subLocation": "London"
},
"department": {
"sector": "IT"
}
},
{
"employee": {
"uid": 2,
"empName": "Mike"
},
"location": {
"country": "UK",
"subLocation": "Manchester"
},
"department": {
"sector": "IT"
}
},
{
"employee": {
"uid": 3,
"empName": "Liya"
},
"location": {
"country": "UK",
"subLocation": "Southampton"
},
"department": {
"sector": "HR"
}
},
{
"employee": {
"uid": 3,
"empName": "Brad"
},
"location": {
"country": "USA",
"subLocation": "Texas"
},
"department": {
"sector": "IT"
}
},
{
"employee": {
"uid": 3,
"empName": "Brad"
},
"location": {
"country": "USA",
"subLocation": "Texas"
},
"department": {
"sector": "NON-IT"
}
}
]
};
but the problem is i'm getting result like
UK : {
location : "UK"
....
}
in html, i don't want to explicitly mention UK with dot operation like below, instead row.location
<ng-container matColumnDef="facility">
<mat-header-cell *matHeaderCellDef mat-sort-header> Facility</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.UK.location}} </mat-cell>
</ng-container>
could someone tell me how to convert this output like
location: {
country : 'UK'
}
or any random name like
obj: {
location: 'UK'
//rest of values for grouping
}
fiddle
Thanks to every one
You can do something like this:
const countryMap = {};
data.response.forEach(item => {
countryMap[item.location.country] = [ ...( countryMap[item.location.country] || [] ), item];
});
Now, this is how the countryMap will look like:
Now, further to map it to the format you want, you can do this:
const mappedData = Object.entries(countryMap).map(entry => ({
location: entry[0],
response: entry[1]
}));
This will produce mappedData in this format:

Extracting values from array of objects

I have an array that looks like this one:
[
{
"users": [
{
"name": "John",
"location": "USA",
"age": "34",
},
{
"name": "John",
"location": "California",
"address": "Silk Road 123"
},
{
"name": "Jane",
"last-name": "Edmus"
"location": "USA"
}
]
},
]
I want to merge the objects whose name match. I found this helper function:
findByMatchingProperties = (set, properties) => {
return set.filter(function (entry) {
return Object.keys(properties).every(function (key) {
return console.log(entry[key] === properties[key]);
});
});
}
But it is not budging. Any ideas on how I could go about this? The expected outcome should be:
[ { "users": [ { "name": "John", "location": ["USA", "California"}, "age": "34", "address": "Silk Road 123" }, { "name": "Jane", "last-name": "Edmus" "location": "USA" } ] }, ]
You could reduce the users array and group them based on the name. Destructure each user and get the name and rest of the properties separately. Loop through the keys of rest and check if the key already exists in the nested value. If it exists, create an array of values. Else, just add the value:
const input = [{users:[{name:"John",location:"USA",age:"34"},{name:"John",location:"California",address:"Silk Road 123"},{name:"Jane","last-name":"Edmus",location:"USA"}]}];
const merged = input[0].users.reduce((acc, o) => {
const { name, ...rest } = o;
const group = acc[name];
// check if name already exists in the accumulator
if(group) {
Object.keys(rest).forEach(key => {
if(key in group)
group[key] = [].concat(group[key], o[key])
else
group[key] = o[key];
})
}
else
acc[name] = o;
return acc;
},{})
const users = Object.values(merged)
console.log([{ users }])
This is what the merged object looks like:
{
"John": {
"name": "John",
"location": ["USA", "California"],
"age": "34",
"address": "Silk Road 123"
},
"Jane": {
...
}
}
Use Object.values() to get the values of this object to an array
You can achive this by using Map object for optimization and then converting it back to array. Check out code below.
const users = [
{ "name": "John", "location": "USA", "age": "34" },
{ "name": "John", "location": "California", "address": "Silk Road 123" },
{ "name": "John", "location": "Foo", "bar": "baz" },
{ "name": "Jane", "last-name": "Edmus", "location": "USA" }
];
const mergeObjectsExceptProps = (exceptProps, o1, o2) =>
Object.entries(o2).reduce((acc, [ k, v ]) => {
if (exceptProps.includes(k)) {
return acc
}
let propValueToSet
if (acc.hasOwnProperty(k)) {
propValueToSet = [
...(Array.isArray(acc[k]) ? acc[k] : [ acc[k] ]),
v
]
} else {
propValueToSet = v
}
return {
...acc,
[k]: propValueToSet,
}
}, o1)
const usersMap = new Map()
for (const user of users) {
const foundUser = usersMap.get(user.name)
if (foundUser) {
usersMap.set(user.name, mergeObjectsExceptProps([ 'name' ], foundUser, user))
} else {
usersMap.set(user.name, user)
}
}
const result = [ ...usersMap.values() ]
console.log(result)

Push value of key from array to another array in a for loop JavaScript

I am trying to push a value from a key that exists in the first array. This array consists of a country_users array that I have looped through every users array within this one and pushed these to a new array called users
In this demo I am trying to push country from country_users to every user object in the users array.
I am using Vue.js for this purpose, it might be easier with Vue? Any suggestions?
var users = [];
var country_users = [
{
"country": "United States",
"users": [
{
"name": "John"
},
{
"name": "Jane"
},
],
},
{
"country": "Norway",
"users": [
{
"name": "Ola"
},
{
"name": "Jens"
},
],
},
];
// Here I push all users from country_users into a new array called users
for (let cu = 0; cu < country_users.length; cu++) {
for (let u = 0; u < country_users[cu].users.length; u++) {
users.push(country_users[cu].users[u]);
}
// Do I make a new for loop here to push the country into every object inside users array? How?
}
console.log(users);
I want to push the country from the array where the users belonged previously.
The result I want is an array like this for users
var users = [
{
"name": "John",
"country": "United States"
},
{
"name": "Jane",
"country": "United States"
},
{
"name": "Ola",
"country": "Norway"
},
{
"name": "Jens",
"country": "Norway"
}
];
console.log(users);
SOLUTION
var users = [];
var country_users = [
{
"country": "United States",
"users": [
{
"name": "John"
},
{
"name": "Jane"
},
],
},
{
"country": "Norway",
"users": [
{
"name": "Ola"
},
{
"name": "Jens"
},
],
},
];
country_users.forEach((country_user) => {
country_user.users.forEach((user) => {
user.country = country_user.country;
users.push(user);
});
});
console.log(users);
You could iterate the given array and their user array and build a new array with the wanted properties.
var country_users = [{ country: "United States", users: [{ name: "John" }, { name: "Jane" }] }, { country: "Norway", users: [{ name: "Ola" }, { name: "Jens" }] }],
users = country_users.reduce(function (r, country) {
country.users.forEach(function (user) {
r.push({ name: user.name, country: country.country });
});
return r;
}, []);
console.log(users);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6
var country_users = [{ country: "United States", users: [{ name: "John" }, { name: "Jane" }] }, { country: "Norway", users: [{ name: "Ola" }, { name: "Jens" }] }],
users = country_users.reduce((r, { country, users }) => {
users.forEach(({ name }) => r.push({ name, country }));
return r;
}, []);
console.log(users);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use Array.prototype.reduce and in each iteration, you create and return the new array with users and countries:
const country_users = [
{
"country": "United States",
"users": [
{
"name": "John"
},
{
"name": "Jane"
},
],
},
{
"country": "Norway",
"users": [
{
"name": "Ola"
},
{
"name": "Jens"
},
],
},
];
const result = country_users.reduce((prev, curr) => {
const users = curr.users.map(user => ({
name: user.name,
country: curr.country
}))
return [
...prev,
...users,
]
}, [])
console.log(result)
Just add the property country before pushing
var users = [];
var country_users = [
{
"country": "United States",
"users": [
{
"name": "John"
},
{
"name": "Jane"
},
],
},
{
"country": "Norway",
"users": [
{
"name": "Ola"
},
{
"name": "Jens"
},
],
},
];
// Here I push all users from country_users into a new array called users
for (let cu = 0; cu < country_users.length; cu++) {
for (let u = 0; u < country_users[cu].users.length; u++) {
var newUser = country_users[cu].users[u];
newUser.country = country_users[cu].country;
users.push(newUser);
}
// Do I make a new for loop here to push the country into every object inside users array? How?
}
console.log(users);
Suggest you to use an ES6 syntax :
for(const country of country_users) {
for(const user of country.users) {
users.push({
...user,
country : country.country
})
}
}
the user object is copied by using rest operator "..."

Categories

Resources