Rebuild nested array - javascript

I have an nested array that i want to rebuild based on age value:
//Data
data = {"people":
[{"male_1": [
{"name": "Bob" ,"age": "32"},
{"name":"Mike", "age":"31"}
]},
{"female_2": [
{"name":"Jessica", "age": "24"},
{"name":"Ann", "age": "23"}
]}
[{"male_3": [
{"name": "Tom" ,"age": "31"},
{"name":"John", "age":"29"}
]}, ...
]}
New array should looks like:
people = [{"male_1": [
{"name": "Bob" ,"age": "32"}
]},
[{"male_3": [
{"name": "Tom" ,"age": "31"}
]},
{"female_2": [
{"name":"Jessica", "age": "24"}
]}, ...
]}
Based on this example i need to find the largest age of all "persons" then add this person to array then do same with the next one. The age can be same in this case there is no difference who goes first.
With the next function i can find first one and push it to new array, but how find next one?
var age = 0;
data["people"].forEach(function(item) {
for (var key in item) {
if (item.hasOwnProperty(key)) {
item[key].forEach(function(person) {
if (person.age > age) {
age = person.age;
oldest_person = person
}
});
}
}
});
console.log(oldest_person);

here is another interpretation. This one uses the native Array.prototype.sort as the helper function.
var data = { "people": [{ "male_1": [{ "name": "Bob", "age": "32" }, { "name": "Mike", "age": "31" }] }, { "female_2": [{ "name": "Jessica", "age": "24" }, { "name": "Ann", "age": "23" }] }, { "male_3": [{ "name": "Tom", "age": "31" }, { "name": "John", "age": "29" }] }] },
oldies = [],
peopleByAge = data.people.map(function(group){
for( var name in group ){
group[name] = group[name].sort(sortBy('age'));
oldies.push( group[name][0] );
}
return group;
});
// sort by an object key
function sortBy( key ){
return function(a, b){
return parseInt(a[ key ]) < parseInt(b[ key ]);
}
}
document.write('<pre>' + JSON.stringify({ oldies: oldies.sort(sortBy('age')), peopleByAge: peopleByAge }, 0, 2) + '</pre>');

Try this:
var age = 0;
var oldest_person = [];
var data = {"people":
[
{"male_1": [
{"name": "Bob" ,"age": "32"},
{"name":"Mike", "age":"31"}
]},
{"female_2": [
{"name":"Jessica", "age": "24"},
{"name":"Ann", "age": "23"}
]},
{"male_3": [
{"name": "Tom" ,"age": "31"},
{"name":"John", "age":"29"}
]}
]};
data["people"].forEach(function(item) {
for (var key in item) {
if (item.hasOwnProperty(key)) {
var age = 0;
var name = key;
var oldest = null;
item[key].forEach(function(person) {
// Determine the oldest person in each group ("male_1", "female_2", "male_3", ...)
if (person.age > age) {
age = person.age;
oldest = person;
}
});
// Push the oldest person into the 'oldest_person' array
var group = {};
group[name] = [ oldest ];
oldest_person.push(group);
}
}
});
console.log(oldest_person);

You can use some Array methods, like Array.prototype.forEach(), Array.prototype.reduce() and Object.keys().
var data = { "people": [{ "male_1": [{ "name": "Bob", "age": "32" }, { "name": "Mike", "age": "31" }] }, { "female_2": [{ "name": "Jessica", "age": "24" }, { "name": "Ann", "age": "23" }] }, { "male_3": [{ "name": "Tom", "age": "31" }, { "name": "John", "age": "29" }] }] },
people = [];
data.people.forEach(function (a) {
Object.keys(a).forEach(function (k) {
var o = {};
o[k] = a[k].reduce(function (c, d) {
return c.age > d.age ? c : d;
});
people.push(o);
});
});
document.write('<pre>' + JSON.stringify(people, 0, 4) + '</pre>');

Related

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)

How to map json object to array

I have json:
{
"userList":
[{
"name": "Bob",
"age": 28
},{
"name": "Tom",
"age": 45
},{
"name": "Alice",
"age": 32
}]
}
I want to cut only age and put them to array like : public mainChartData1: Array = [28, 45, 32];
I have started to do that by next code:
const arr = this.users.map(obj => {
var localObj = [];
localObj[obj] = obj.age;
return localObj;
});
But it doesn't work.
You can use a little map function to extract the array age
const inputObject = {
"userList":
[{
"name": "Bob",
"age": 28
},{
"name": "Tom",
"age": 45
},{
"name": "Alice",
"age": 32
}]
};
const output = inputObject.userList.map(user => user.age);
console.log(output);
Say arrayObject is the object you have, following should do it. map will return a new array that will be assigned to ageArray.
let ageArray = arrayObject.userList.map(e => e.age)

Append Multiple objects into single array

I have an array of objects of the structure coming from server response of iterated array object like as sample
array[1] ={
"ID": "123",
"Name": "John",
"Age": "15"
}
array[2] ={
"ID": "456",
"Name": "Sue",
"Age": "18"
}
array[n] ={
}
But now I want to append the array values if the condition age below 18 in the following structure of as iterated values of above array
Expected Output:
{
"Stud": [{
"ID": "123",
"Name": "John",
"Age": "15"
}, {
"ID": "456",
"Name": "Sue",
"Age": "18"
},{n........
}]
}
var output = { "Stud" : [] };
for (var i = array.length - 1; i >= 0; i--) {
if (array[i].Age < 18) {
output.Stud.push(array[i]);
}
}
console.log(output);
Simply
var output = { "Stud" : array }; //existing 'array'
You can use array#filter to select objects with age less than or equal to 18.
const response = [{
"ID": "123",
"Name": "John",
"Age": "15"
},{
"ID": "456",
"Name": "Sue",
"Age": "18"
},{
"ID": "459",
"Name": "Jaby",
"Age": "20"
}];
const result = response.filter(o => o.Age <= 18);
var output = {'stud' : result};
console.log(output);
Simply iterate and check whether the age is < 18 or not. If so push that to another array.
var array = [];
var array_below_18 = [];
array[0] ={
"ID": "123",
"Name": "John",
"Age": "15"
}
array[1] ={
"ID": "456",
"Name": "Sue",
"Age": "18"
}
array[1] ={
"ID": "456",
"Name": "Sue",
"Age": "14"
}
for(i=0;i<array.length;++i){
if(parseInt(array[i].Age)<18){
array_below_18.push(array[i]);
}
}
var final_object = {
"Stud" : array_below_18
}
console.log(final_object);

creating new object with values of another object in javascript

How can we change the structure of the below data object using JavaScript. Needs to categorize all the names under the std. Thanks in advance
[
{
"name": "Rohan",
"std": "3"
},
{
"name": "Jack",
"std": "2"
},
{
"name": "Peter",
"std": "2"
}
]
to
[
{
"std": "2",
"details": [
{
"name": "Jack"
},
{
"name": "Peter"
}
]
},
{
"std": "3",
"details": [
{
"name": "Rohan"
}
]
}
]
The solution using Array.forEach, Array.map and Object.keys functions:
var arr = [{"name": "Rohan", "std": "3"}, { "name": "Jack", "std": "2" }, { "name": "Peter", "std": "2" }],
grouped = {}, result;
arr.forEach(function(obj){
var std = obj['std'];
if (this[std]) {
this[std]['details'].push({'name' : obj['name']});
} else {
this[std] = {'std' : std, 'details' : [{'name' : obj['name']}]};
}
}, grouped);
result = Object.keys(grouped).map((k) => grouped[k]);
console.log(JSON.stringify(result, 0, 4));
The output:
[
{
"std": "2",
"details": [
{
"name": "Jack"
},
{
"name": "Peter"
}
]
},
{
"std": "3",
"details": [
{
"name": "Rohan"
}
]
}
]
You can use reduce() method here
var data = [{
"name": "Rohan",
"std": "3"
}, {
"name": "Jack",
"std": "2"
}, {
"name": "Peter",
"std": "2"
}],
res = [],
kmap = {};
res = data.reduce(function(a, b) {
// check std value already in array using kmap object
if (kmap[b.std]) {
// if already exist then push name attribute in the details
a[kmap[b.std] - 1].details.push({
'name': b.name
});
} else {
// in else case push the new object
a.push({
'std': b.std,
'details': [{
'name': b.name
}]
});
kmap[b.std] = a.length; // storing the (index + 1) value to avoid 0 in if condition
}
return a;
}, []);
console.log(res);
For older browsers check polyfill option for reduce method.
Problems like this are good candidates for recursion. Here is one possible recursive solution. You can make it much prettier using a functional programming framework such as underscore.js.
var objs = [
{
"name": "Rohan",
"std": "3"
},
{
"name": "Jack",
"std": "2"
},
{
"name": "Peter",
"std": "2"
}
];
function categorize(objs) {
if (objs.length === 0) {
return [];
} else {
var first = objs.shift();
var categorized = categorize(objs);
for(var i = 0; i < categorized.length; i++) {
if (categorized[i].std === first.std) {
categorized[i].details.push({name: first.name});
break;
}
}
if(i === categorized.length) {
categorized.push({std: first.std, details: [{name: first.name}]});
}
return categorized;
}
}
var res = categorize(objs);
console.log(res);
If you're using lodash (I know the question didn't ask this and it's going to be slower, but it may be useful to someone :))
var data = [
{ "name": "Rohan", "std": "3" },
{ "name": "Jack", "std": "2" },
{ "name": "Peter", "std": "2" }
];
var grouped = _.chain(data)
.groupBy('std')
.map(function (people, std) {
return {
std: std,
details: _.map(people, function(person) {
return { name: person.name };
})
}
}).value();

sum numeric values in a multidimentional array

I have an array like this in Javascript:
var scores = [
{"firstName":"John", "value": 89},
{"firstName":"Peter", "value": 151},
{"firstName":"Anna", "value": 200},
{"firstName":"Peter", "value": 22},
{"firstName":"Anna","value": 60}
];
I would like to transform this array so that the values of similar first names are combined. My desired outcome is:
var scores = [
{"firstName":"John", "value": 89},
{"firstName":"Peter", "value": 173},
{"firstName":"Anna", "value": 260}
];
Regards,
Just:
var scores = [{
"firstName": "John",
"value": 89
}, {
"firstName": "Peter",
"value": 151
}, {
"firstName": "Anna",
"value": 200
}, {
"firstName": "Peter",
"value": 22
}, {
"firstName": "Anna",
"value": 60
}];
var names = {};
var new_arr = [];
scores.forEach(function(entry) {
if (names.hasOwnProperty(entry.firstName)) {
new_arr[names[entry.firstName]].value += entry.value;
} else {
names[entry.firstName] = new_arr.length;
new_arr.push({
"firstName": entry.firstName,
"value": entry.value
});
}
});
console.log(new_arr);
This is a two step solution. First count all items. And second, format the result to the wanted style.
var scores = [
{ "firstName": "John", "value": 89 },
{ "firstName": "Peter", "value": 151 },
{ "firstName": "Anna", "value": 200 },
{ "firstName": "Peter", "value": 22 },
{ "firstName": "Anna", "value": 60 }
];
var result = [],
r0 = scores.reduce(function (r, a) {
r[a.firstName] = (r[a.firstName] || 0) + a.value;
return r;
}, {}), // { "John": 89, "Peter": 173, "Anna": 260 }
i;
for (i in r0) {
result.push({ firstName: i, value: r0[i] });
}
document.getElementById('out').innerHTML = JSON.stringify(result, null, 4);
<pre id="out"></pre>
var result = [],
names = [],
index;
var scores = [
{"firstName":"John", "value": 89},
{"firstName":"Peter", "value": 151},
{"firstName":"Anna", "value": 200},
{"firstName":"Peter", "value": 22},
{"firstName":"Anna","value": 60}
];
scores.forEach(function (score) {
index = names.indexOf(score.firstName);
if (index === -1) {
index = names.push(score.firstName) - 1;
result.push({firstName: score.firstName, value: 0});
}
result[index].value += score.value;
});
console.log(result);

Categories

Resources