Extracting values from array of objects - javascript

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)

Related

Refactor to use reduce for grouping array of objects by nested array text

I have a function that will accept 3 arguments; an array of data, a key and a partial value. I want to group the results by a value that may be in each objects nested array. It looks like my code is working, but I'm wondering if refactoring to use reduce would be better. Here is what I have:
const arr = [
{
"id": "vghjnbghjkoijhjnmkjhjk",
"region": "US",
"tags": ["tag1:bvghjhgh","tag2:bvghjkjnm","tag3:vghjbghj"]
},
{
"id": "cvbhyt56789-mnbvghyu76",
"region": "US",
"tags": ["tag1:bvghjhgh"]
},
{
"id": "ghjkjnbhjnbhjkmnhjkmjk",
"region": "US",
"tags": ["tag2:bvghjkjnm"]
},
{
"id": "ghjkjnbhjnbhjkmnhjkmjk",
"region": "US",
"tags": []
},
{
"id": "bghjkjnbghjkjnhjnbhjhj",
"region": "CA",
"tags": ["tag1:bvghjhgh","tag3:vghjbghj"]
}
];
The expected results are as follows, based on a key of tags and a value of tag1:
[
[
{
"id": "vghjnbghjkoijhjnmkjhjk",
"region": "US",
"tags": ["tag1:bvghjhgh","tag2:bvghjkjnm","tag3:vghjbghj"]
},
{
"id": "cvbhyt56789-mnbvghyu76",
"region": "US",
"tags": ["tag1:bvghjhgh"]
},
{
"id": "bghjkjnbghjkjnhjnbhjhj",
"region": "CA",
"tags": ["tag1:bvghjhgh","tag3:vghjbghj"]
}
],
[
{
"id": "ghjkjnbhjnbhjkmnhjkmjk",
"region": "US",
"tags": ["tag2:bvghjkjnm"]
},
{
"id": "ghjkjnbhjnbhjkmnhjkmjk",
"region": "US",
"tags": []
},
]
]
Here is my current function:
function groupData(arr, key, value) {
const grouped = {};
const remaining = [];
for (const obj of arr) {
const index = obj[key].findIndex(elem => elem.includes(value));
if (index > -1) {
const groupByKey = obj[key][index];
if (grouped.hasOwnProperty(groupByKey)) {
grouped[groupByKey].push(obj);
} else {
grouped[groupByKey] = [obj];
}
} else {
remaining.push(obj);
}
}
return [Object.values(grouped).flat(), noMatch];
}
I provide a solution using reduce() and map,but compared with other answers,seems groupby is a better choice
const arr = [
{
"id": "vghjnbghjkoijhjnmkjhjk",
"region": "US",
"tags": ["tag1:bvghjhgh","tag2:bvghjkjnm","tag3:vghjbghj"]
},
{
"id": "cvbhyt56789-mnbvghyu76",
"region": "US",
"tags": ["tag1:bvghjhgh"]
},
{
"id": "ghjkjnbhjnbhjkmnhjkmjk",
"region": "US",
"tags": ["tag2:bvghjkjnm"]
},
{
"id": "ghjkjnbhjnbhjkmnhjkmjk",
"region": "US",
"tags": []
},
{
"id": "bghjkjnbghjkjnhjnbhjhj",
"region": "CA",
"tags": ["tag1:bvghjhgh","tag3:vghjbghj"]
}
];
let mdata = {'tags':'tag1'}
let entries = Object.entries(mdata).flat()
let key = entries[0],value = entries[1]
let result = arr.reduce((a,c) => {
let exists = c[key].some(i => i.startsWith(value + ':'))
let skey = exists ? value: 'other'
let obj = a.find(a => a[skey])
if(obj){
obj[skey].push(c)
}else{
obj = {[skey]:[c]}
a.push(obj)
}
return a
},[])
result = result.map(d => d[value]||d.other)
console.log(result)
A generic groupBy (similar functions exist in popular libraries like LoDash) would help here:
const groupBy = (iterable, keyFn) => {
const groups = new Map();
for (const x of iterable) {
const key = keyFn(x);
let group = groups.get(key);
if (group === undefined) {
groups.set(key, group = []);
}
group.push(x);
}
return groups;
};
Then you have:
const groupData = (arr, key, value) => {
const groups = groupBy(arr, obj =>
obj[key].find(elem => elem.includes(value)));
const noMatch = groups.get(undefined);
groups.delete(undefined);
return [[...groups.values()].flat(), noMatch];
};

How to iterate over JSON files

I am getting JSON data from two links, below is the structure of the files:
Stocks:
[{
"id": "efcd1502-265b-4e39-9a62-d8fbd96d49bb",
"stock_name": "AcelRx Pharmaceuticals, Inc.",
"shareholders": [{
"userId": "5d43449f-17a8-4747-b89a-ec2dd54b83ee",
"number_of_shares": 378
}, {
"userId": "91bef464-b2ee-4c18-8d9d-0781d30a3bcb",
"number_of_shares": 358
}, {
"userId": "c4a0c9ff-b934-4eda-b9fb-bd26afa21561",
"number_of_shares": 351
}, {
"userId": "2a9fd876-334f-425d-9135-4211ca92a886",
"number_of_shares": 499
}]
}]
People:
[{
"id": "20035a09-3820-4f49-bb8f-d947cebee537",
"first_name": "Merell",
"last_name": "Pecht",
"email": "mpecht0#uol.com.br",
"ip_address": "159.113.166.2",
"ssn": "819-97-0464",
"date_of_birth": "12/12/1998",
"address": {
"home": {
"street_number": "862",
"street_name": "Starling",
"street_suffix": "Hill",
"city": "Riverside",
"state": "CA",
"zip": "92519"
},
"work": {
"street_number": "3",
"street_name": "Grayhawk",
"street_suffix": "Circle",
"city": "Tucson",
"state": "AZ",
"zip": "85710"
}
}
}]
Below is my code for replacing the userID present in Stocks' shareholders array with first name and last name from the people file wherever the ID matches.
require("util").inspect.defaultOptions.depth = null;
const axios = require('axios');
async function getPeople(){
const { data } = await axios.get('https://gist.githubusercontent.com/graffixnyc/a1196cbf008e85a8e808dc60d4db7261/raw/9fd0d1a4d7846b19e52ab3551339c5b0b37cac71/people.json')
return data // this will be the array of people objects
}
async function getStocks(){
const { data } = await axios.get('https://gist.githubusercontent.com/graffixnyc/8c363d85e61863ac044097c0d199dbcc/raw/7d79752a9342ac97e4953bce23db0388a39642bf/stocks.json')
return data // this will be the array of people objects
}
async function listShareholders(){
let a = await getPeople();
let b = await getStocks();
let arr = {}
for(j=0;j<b.length;j++){
for(k=0;k<b[j].shareholders.length;k++){
let shareholders = []
let res = {}
for(i=0;i<a.length;i++){
if(b[j].shareholders[k].userId === a[i].id){
res['first_name'] = a[i].first_name
res['last_name'] = a[i].last_name
res['number of shares'] = b[j].shareholders[k].number_of_shares
shareholders.push(res)
arr['id'] = b[j].id
arr['stock_name'] = b[j].stock_name
arr['shareholders'] = shareholders
}
}
}
}
return arr
}
async function bc(){
const address = await listShareholders()
console.log(address)
}
bc()
The output is just one stock with the userID replaced with the name which is the last object in the stocks file. Below is the output I get. I actually need to get all of the stocks with the ID replaced. Not sure what I am doing wrong
{
id: 'efcd1502-265b-4e39-9a62-d8fbd96d49bb',
stock_name: 'AcelRx Pharmaceuticals, Inc.',
shareholders: [
{
first_name: 'Jenni',
last_name: 'Garrish',
'number of shares': 499
}
]
}
Code :
require("util").inspect.defaultOptions.depth = null;
const axios = require('axios');
async function getPeople(){
const { data } = await axios.get('https://gist.githubusercontent.com/graffixnyc/a1196cbf008e85a8e808dc60d4db7261/raw/9fd0d1a4d7846b19e52ab3551339c5b0b37cac71/people.json')
return data // this will be the array of people objects
}
async function getStocks(){
const { data } = await axios.get('https://gist.githubusercontent.com/graffixnyc/8c363d85e61863ac044097c0d199dbcc/raw/7d79752a9342ac97e4953bce23db0388a39642bf/stocks.json')
return data // this will be the array of people objects
}
async function listShareholders(){
let a = await getPeople();
let b = await getStocks();
b.forEach(stockItem => {
stockItem.shareholders = stockItem.shareholders.map(shareHolderItem => {
const person = a.find(e => e.id == shareHolderItem.userId);
return { first_name: person?.first_name,last_name: person?.last_name,number_of_shares: shareHolderItem.number_of_shares}
});
//Keep this if you just want to show mapped shareholder only
stockItem.shareholders = stockItem.shareholders.filter(e => e.first_name !== undefined);
return b
});
}
async function bc(){
const address = await listShareholders()
console.log(address)
}
bc()
You should use Array.map in case you want to change/map to a new structure.
const stocks = [{
"id": "efcd1502-265b-4e39-9a62-d8fbd96d49bb",
"stock_name": "AcelRx Pharmaceuticals, Inc.",
"shareholders": [{
"userId": "5d43449f-17a8-4747-b89a-ec2dd54b83ee",
"number_of_shares": 378
}, {
"userId": "91bef464-b2ee-4c18-8d9d-0781d30a3bcb",
"number_of_shares": 358
}, {
"userId": "c4a0c9ff-b934-4eda-b9fb-bd26afa21561",
"number_of_shares": 351
}, {
"userId": "2a9fd876-334f-425d-9135-4211ca92a886",
"number_of_shares": 499
}, { // my element to match to Merell Pecht
"userId": "20035a09-3820-4f49-bb8f-d947cebee537",
"number_of_shares": 9999
}]
}];
const people = [{
"id": "20035a09-3820-4f49-bb8f-d947cebee537",
"first_name": "Merell",
"last_name": "Pecht",
"email": "mpecht0#uol.com.br",
"ip_address": "159.113.166.2",
"ssn": "819-97-0464",
"date_of_birth": "12/12/1998",
"address": {
"home": {
"street_number": "862",
"street_name": "Starling",
"street_suffix": "Hill",
"city": "Riverside",
"state": "CA",
"zip": "92519"
},
"work": {
"street_number": "3",
"street_name": "Grayhawk",
"street_suffix": "Circle",
"city": "Tucson",
"state": "AZ",
"zip": "85710"
}
}
}];
stocks.forEach(stockItem => {
stockItem.shareholders = stockItem.shareholders.map(shareHolderItem => {
const person = people.find(e => e.id == shareHolderItem.userId);
return {
first_name: person?.first_name,
last_name: person?.last_name,
number_of_shares: shareHolderItem.number_of_shares
}
});
//Keep this if you just want to show mapped shareholder only
stockItem.shareholders = stockItem.shareholders.filter(e => e.first_name !== undefined);
});
console.log(stocks);
Update: Fix function
async function listShareholders(){
let a = await getPeople();
let b = await getStocks();
b.forEach(stockItem => {
stockItem.shareholders = stockItem.shareholders.map(shareHolderItem => {
const person = a.find(e => e.id == shareHolderItem.userId);
return { first_name: person?.first_name,last_name: person?.last_name,number_of_shares: shareHolderItem.number_of_shares}
});
//Keep this if you just want to show mapped shareholder only
stockItem.shareholders = stockItem.shareholders.filter(e => e.first_name !== undefined);
});
return b // <- This row
}
You can do this using Spread Operator and Array.map() functions:
NOTE: I've taken the liberty to simplify the objects for the sake of the example. This should work for the original object as well
const stocks = [{
"id": "efcd1502-265b-4e39-9a62-d8fbd96d49bb",
"stock_name": "AcelRx Pharmaceuticals, Inc.",
"shareholders": [{
"userId": "1",
"number_of_shares": 378
}, {
"userId": "2",
"number_of_shares": 358
}, {
"userId": "3",
"number_of_shares": 351
}, {
"userId": "4",
"number_of_shares": 499
}]
}]
const people = [{
"id": "1",
"first_name": "Tony",
"last_name": "Stark",
},
{
"id": "2",
"first_name": "Steve",
"last_name": "Rogers",
},
{
"id": "3",
"first_name": "Bruce",
"last_name": "Banner",
},
{
"id": "4",
"first_name": "Thor",
"last_name": "Odinson",
}]
const result = stocks.map(stock => {
return {
...stock,
shareholders: stock.shareholders.map(shareHolder => {
const {first_name, last_name} = people.find(person => person.id === shareHolder.userId);
return {
...shareHolder,
first_name,
last_name
}
})
}
})
console.log(JSON.stringify(result, null, 2));

Search key and return value in nested object

Lets say my object looks like the below. Its a mix of different arrays and parents, no hierarchical order. e.g.
"person": {
"id": 12345,
"name": "John Doe",
"emergencyContacts": [
{
"name": "Jane Doe",
"phone": "888-555-1212",
"relationship": "spouse",
"moreDetails": {
"id": 12345,
"phones": {},
"home": "800-123-4567",
"mobile": "877-123-1234"
}
},
{
"name": "Justin Doe",
"phone": "877-123-1212",
"relationship": "parent",
"mobile": "877-123-1234"
}
],
"workContacts": [
{
"name": "Jane Doe",
"phone": "888-555-1212",
"relationship": "spouse",
"moreworkDetails": {
"id": 12345,
"phones": {},
"home": "800-123-4567",
"mobile": "877-123-1234"
}
},
{
"name": "Justin Doe",
"phone": "877-123-1212",
"relationship": "parent",
"mobile": "877-123-1234"
}
]
}
I want to be able to search the entire object of person and bring back the value of the key mobile. I am guessing that the object needs to be flattened and a new array created with the list of "unique" mobile numbers found e.g.
var mobile = {
0: 888-555-1212,
1: 800-123-4567,
2: 877-123-1234,
3: 083-111-3346
}
I have searched for solutions in pure js and lodash, however each one found is knowing what the parent is called and depth of the array - lets assume the parent and depth could be limitless(this sets it aside from question Find by key deep in a nested object). Any help would be muchly appreciated. Thanks
You will need a recursive function. For explanation please check the comments
let person = {
"id": 12345,
"name": "John Doe",
"emergencyContacts": [{
"name": "Jane Doe",
"phone": "888-555-1212",
"relationship": "spouse",
"moreDetails": {
"id": 12345,
"phones": {},
"home": "800-123-4567",
"mobile": "877-123-1234"
}
},
{
"name": "Justin Doe",
"phone": "877-123-1212",
"relationship": "parent",
"mobile": "877-123-1234"
}
],
"workContacts": [{
"name": "Jane Doe",
"phone": "888-555-1212",
"relationship": "spouse",
"moreworkDetails": {
"id": 12345,
"phones": {},
"home": "800-123-4567",
"mobile": "877-123-1236"
}
},
{
"name": "Justin Doe",
"phone": "877-123-1212",
"relationship": "parent",
"mobile": "877-123-1235"
}
]
}
let arrys = [];
//iterate the object
function recursive(obj, key) {
//iterate the object
for (let keys in obj) {
// check if the key name is same as the desired one
if (keys === key) {
// then push the value to an array
arrys.push(obj[keys])
} else {
// if the value of a key is an array & if it is not empty
if (Array.isArray(obj[keys]) && obj[keys].length > 0) {
// iterate the array. in each iteration you will get the object
// example emergencyContacts. In each iteration
// call the same function with new data
obj[keys].forEach(function(item) {
// pass that object to the same function
recursive(item, key)
})
}
// if the value is an object then again call the same function
else if (typeof obj[keys] === 'object') {
recursive(obj[keys], key)
}
}
}
}
recursive(person, 'mobile');
//create object from the array
let newObj = {}
for (let m = 0; m < arrys.length; m++) {
newObj[m] = arrys[m]
}
console.log(newObj)
You don't need recursion. You can do it with while loop:
function searchFor(what, where) {
const stack = [where];
const result = [];
while (stack.length) {
const item = stack.pop();
if (Array.isArray(item)) {
item.forEach(el => stack.push(el));
continue;
}
if (item && typeof item === "object")
Object.entries(item).forEach(([key, value]) =>
key === what ?
result.push(value) :
stack.push(value)
)
}
return result;
}
I generalized it a bit with code shamelessly stolen from my own lib: goodcore
I chose a recursice approach since I believe the code is much easier to analyze although it has more code.
let obj = {
"id": 12345,
"name": "John Doe",
"emergencyContacts": [{
"name": "Jane Doe",
"phone": "888-555-1212",
"relationship": "spouse",
"moreDetails": {
"id": 12345,
"phones": {},
"home": "800-123-4567",
"mobile": "877-123-1234"
}
},
{
"name": "Justin Doe",
"phone": "877-123-1212",
"relationship": "parent",
"mobile": "877-123-1234"
}
],
"workContacts": [{
"name": "Jane Doe",
"phone": "888-555-1212",
"relationship": "spouse",
"moreworkDetails": {
"id": 12345,
"phones": {},
"home": "800-123-4567",
"mobile": "877-123-1236"
}
},
{
"name": "Justin Doe",
"phone": "877-123-1212",
"relationship": "parent",
"mobile": "877-123-1235"
}
]
};
function isObject(it) {
return it !== null && typeof it === "object";
}
function isArray(it) {
return Array.isArray ? Array.isArray(it) : Object.prototype.toString.call(it) === "[object Array]";
}
function forEach(target, fn) {
if(isArray(target)) {
target.forEach(fn);
} else {
Object.entries(target).forEach(([key, value]) => fn(value, key));
}
}
function objReduce(obj, fn, acc) {
let a = acc;
forEach(obj, (value, key) => {
if(isObject(value) || isArray(value)) {
a = objReduce(value, fn, a);
}
a = fn(a, value, key);
});
return a;
}
objReduce(obj, (acc, cur, key) => {
if(key === "mobile") {
acc.push(cur);
}
return acc;
}, []);
Basically what it does is that it creats an object reduce function that loops over all properties and runs an accumulator function on it much like Array.prototype.reduce does for arrays. It needed a bit of code since it handles arrays and objects arbitrarily.
returnValuesForAttribute = (attr) => {
let mobile = {};
let index = 0;
Object.values(person).map(first_level => {
if (Array.isArray(first_level)) {
first_level.map(el => {
if (Object.keys(el).includes(attr)) {
mobile[index] = el[attr];
index++;
}
Object.values(el).map(second_level => {
if (typeof second_level === 'object' && second_level[attr]) {
mobile[index] = second_level[attr];
index++;
}
})
})
}
});
return mobile;
}
returnValuesForAttribute('mobile');
Output: {0: "877-123-1234", 1: "877-123-1234", 2: "877-123-1234", 3: "877-123-1234"}
detect the key in deeply nested object and return the value of key.
function getPropFromObj(obj, prop) {
let valueToFindByKey;
if (!Array.isArray(obj) && obj !== null && typeof obj === "object") {
if (obj.hasOwnProperty(prop)) {
valueToFindByKey = obj[prop];
console.log(valueToFindByKey);
} else {
let i;
for (i = 0; i < Object.keys(obj).length; i++) {
getPropFromObj(obj[Object.keys(obj)[i]], prop);
}
}
}
return null;
}
const objToInvestigate = {
employeeInformation: {
employees: {
name: "venky",
age: 27,
job: "Frontend Developer",
},
},
};
getPropFromObj(objToInvestigate, "name");

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 "..."

Rebuild nested array

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>');

Categories

Resources