I have an object that looks like the following:
const test = {
leagues: [
{
timezone: "GMT",
date: "1/2/2",
premierLeague: [
{ name: "Liverpool", age: 1892 },
{ name: "Manchester Utd", age: 1878 }
],
laLiga: [
{
team: "Real Madrid",
stadium: "Bernabeu"
},
{
team: "Barcelona",
stadium: "Camp Nou"
}
]
}
]
};
and I want the result to look like
const result = [
{ name: "Liverpool", age: 1892 },
{ name: "Manchester Utd", age: 1878 },
{
team: "Real Madrid",
stadium: "Bernabeu"
},
{
team: "Barcelona",
stadium: "Camp Nou"
}
];
I have tried to use flat() but am having trouble getting the arrays within the leagues. The result will be dynamic so I need to be able to get all the arrays within leagues. Can anyone point me in the correct direction to do this?
If your object structure doesn't go an deeper than that, this long one-liner should work:
const result = test.leagues.reduce((arr, obj) => Object.values(val).reduce((innerArr, val) => Array.isArray(val) ? innerArr.concat(val) : innerArr, arr), []);
Somewhat ungolfed:
const result = test.leagues.reduce((arr, obj) => {
return Object.values(val).reduce((innerArr, val) => {
return Array.isArray(val)
? innerArr.concat(val)
: innerArr
}, arr);
}), []);
You might be looking for
const result = test.leagues.flatMap(league =>
Object.values(league).filter(Array.isArray).flat()
);
This sounds weird, you'll end up with objects of different shapes in the same array. I'm not sure how you'll deal with that.
It looks like you're trying to concatenate every value of test.leagues that is itself an array.
const test = {
leagues: [{
timezone: "GMT",
date: "1/2/2",
premierLeague: [{
name: "Liverpool",
age: 1892
},
{
name: "Manchester Utd",
age: 1878
}
],
laLiga: [{
team: "Real Madrid",
stadium: "Bernabeu"
},
{
team: "Barcelona",
stadium: "Camp Nou"
}
]
}]
};
const output = [];
for (const league of test.leagues) {
for (const key in league) {
if (Array.isArray(league[key])) {
// Push each element in `league[key]` onto `output`
// so we don't have to flatten it later
output.push(...league[key]);
}
}
}
console.log({
output
});
Well, I'm also adding my 2 cents over here. I do agree with everyone else. See if this works:
const test = {
leagues: [
{
timezone: "GMT",
date: "1/2/2",
premierLeague: [
{ name: "Liverpool", age: 1892 },
{ name: "Manchester Utd", age: 1878 }
],
laLiga: [
{
team: "Real Madrid",
stadium: "Bernabeu"
},
{
team: "Barcelona",
stadium: "Camp Nou"
}
]
}
]
};
let finalArray = [];
function recursiveArr(obj, arrayToPush) {
for(const [key, val] of Object.entries(obj)) {
if(Array.isArray(obj[key])) {
arrayToPush.push(obj[key]);
continue;
}
const type = typeof obj[key];
if(type === "object") {
recursiveArr(obj[key], arrayToPush);
}
}
}
recursiveArr(test.leagues, finalArray);
console.log(finalArray.flat())
Related
I'm trying to convert array of objects having value as a array -> into string. I'm facing blocker in this,
let peopleDetails = [
{
name: "raj",
favCar: [{ name: "audi", color: "white" }],
favFood: [{ color: "brown", name: "Idli" }],
},
{ name: "deepak", place: "India", favPlace: [{ name: "Tajmahal" }] },
];
I need structure like,
let peopleDetails = [
{ name: "raj", favCar: "audi", favFood: "Idli" },
{ name: "deepak", place: "India", favPlace: "Tajmahal" },
];
For what I understand you want the value of every property to become the name value of its first element, when the value is an array of object.
Here's an immutable solution that follows this concept:
let peopleDetails = [
{
name: 'raj',
favCar: [{ name: 'audi', color: 'white' }],
favFood: [{ name: 'Idli' }],
},
{ name: 'deepak', place: 'India', favPlace: [{ name: 'Tajmahal' }] },
];
const result = peopleDetails.map(obj =>
Object.fromEntries(Object.entries(obj).map(([key, value]) =>
[key, value?.[0]?.name ?? value]
))
);
console.log(result);
I'm not sure why you've got arrays of singular elements (favourites typically don't have second or third places) so if you just want to extract the name from each item that's an array, take it from the first element in each array:
let peopleDetails = [{
name: "raj",
favCar: [{
name: "audi",
color: "white"
}],
favFood: [{
name: "Idli"
}],
},
{
name: "deepak",
place: "India",
favPlace: [{
name: "Tajmahal"
}]
},
];
let peopleDetailsModified = peopleDetails.map(o => {
let retObj = {};
for (key in o) {
if (Array.isArray(o[key])) {
retObj[key] = o[key][0].name;
} else {
retObj[key] = o[key];
}
}
return retObj;
});
console.log(peopleDetailsModified);
I've made this code more verbose than it needs to be, it's quite easy to one-line it using reduce.
I'm also quite not sure what you're trying to achieve as the other answers but I tried to make a map of the current object to an object that is more to your liking. I formatted it a little so you can see what I did:
peopleDetails.map(item => {
return {
name: item.name,
place: item.place,
favCar: item.favCar ? item.favCar[0].name : "",
favPlace: item.favPlace ? item.favPlace[0].name : "",
favFood: item.favFood ? item.favFood[0].name : ""}});
I have ran the code and its a generic code for similar data
const _ = require('lodash')
const peopleDetails =[
{
"name": "raj",
"favCar": [
{
"name": "audi",
"color": "white"
}
],
"favFood": [
{
"name": "Idli"
}
]
},
{
"name": "deepak",
"place": "India",
"favPlace": [
{
"name": "Tajmahal"
}
]
}
]
const newPeopleDetails = peopleDetails.map(obj => {
const formObj = {
favCar: obj && obj.favCar && obj.favCar[0].name,
favFood: obj && obj.favFood && obj.favFood[0].name,
favPlace: obj && obj.favPlace && obj.favPlace[0].name
}
const finalObj = _.pickBy(formObj, _.identity);
return Object.assign({}, obj, finalObj);
});
console.log(newPeopleDetails)
I want to group an array of objects based on a property which has an array of values,and i want to return a group for each individual value,not only for the whole array.
For example :
let crew = [
{
name:"john",
job :["electrician","carpenter"]
},
{
name: "bill",
job: ["electrician"]
},
{
name: "mark",
job: [ "carpenter"]
}
]
let groupedCrew = _.groupBy(crew,"job")
console.log(groupedCrew)
/*
carpenter:
[
{
job:
[
carpenter
],
name:
"mark"
}
],
electrician:
[
{
job:
[
"electrician"
],
name:
"bill"
}
],
electrician, carpenter:
[
{
job:
[
"electrician",
"carpenter"
],
name:
"john"
}
]
}
*/
In this example i want "john" to also appear in "electrician" group.
Any ideas ?
Once again let's group something using reduce
Here's the basic structure (plus the solution)
let crew = [{
name: "john",
job: ["electrician", "carpenter"]
},
{
name: "bill",
job: ["electrician"]
},
{
name: "mark",
job: ["carpenter"]
}
];
var obj = crew.reduce(function(agg, item) {
// grouping logic below this line
item.job.forEach(function(job) {
agg[job] = agg[job] || []
// agg[job].push (item);
// lets push only name so we can see output
agg[job].push(item.name)
})
// grouping logic above this line
return agg
}, {})
console.log(obj)
use custom .reduce() function
there is no need for lodash
const crew = [
{
name: 'john',
job: ['electrician', 'carpenter'],
},
{
name: 'bill',
job: ['electrician'],
},
{
name: 'mark',
job: ['carpenter'],
},
];
const groupedCrew = crew.reduce((groupedCrew, person) => {
person.job.forEach(job => {
if (!groupedCrew[job]) groupedCrew[job] = [];
groupedCrew[job].push(person);
});
return groupedCrew;
}, {});
console.log(JSON.stringify(groupedCrew, null, 4));
I have a nested array . I want to take values from array and push to new single object.
should read take the _id as object key and category array field should be value for _id
const Ll = [
{
_id: 'milk',
category: [
[
{
name: 'Alfred',
job: 'manager'
},
{
name: 'Mark',
job: 'manager'
}
]
]
},
{
_id: 'grocery',
category: [
[
{
name: 'William',
job: 'manager'
}
]
]
}
]
I want object like so,
const obj = {
milk: [
{
name: 'Alfred',
job: 'manager'
},
{
name: 'Mark',
job: 'manager'
}
],
grocery: [
{
name: 'William',
job: 'manager'
}
]
}
Is possible to do
Thanks!
You could do it using Array.prototype.reduce() method. Traverse the array and group it by _id.
const data = [
{
_id: 'milk',
category: [
[
{
name: 'Alfred',
job: 'manager',
},
],
],
},
{
_id: 'grocery',
category: [
[
{
name: 'William',
job: 'manager',
},
],
],
},
{
_id: 'milk',
category: [
[
{
name: 'Mark',
job: 'manager',
},
],
],
},
];
const ret = data.reduce((prev, c) => {
const p = prev;
const key = c._id;
p[key] = p[key] ?? [];
p[key].push(...c.category.flat());
return p;
}, {});
console.log(ret);
ES6:
const data = [
{
_id: 'milk',
category: [
[
{
name: 'Alfred',
job: 'manager',
},
],
],
},
{
_id: 'grocery',
category: [
[
{
name: 'William',
job: 'manager',
},
],
],
},
{
_id: 'milk',
category: [
[
{
name: 'Mark',
job: 'manager',
},
],
],
},
];
const ret = data.reduce((prev, c) => {
const p = prev;
const key = c._id;
p[key] = p[key] || [];
p[key].push(...c.category.reduce((acc, val) => acc.concat(val), []));
return p;
}, {});
console.log(ret);
Here is solution for you.
const obj = {};
data.forEach(d => {
const categories = d.category.reduce((a, v) => a.concat(v), []);
obj[d._id] = obj[d._id] ? [...obj[d._id], ...categories] : [...categories];
});
console.log(obj);
You could use reduce with empty object accumulated
Technique combined with:
computed property [_id]: category
object destruction (acc, { _id, category }) as well as ({...acc})
const data = [ { _id: "milk", category: [ [ { name: "Alfred", job: "manager", }, { name: "Mark", job: "manager", }, ], ], }, { _id: "grocery", category: [ [ { name: "William", job: "manager", }, ], ], }, ];
const res = data.reduce(
(acc, { _id, category }) => ({ ...acc, [_id]: category.flat() }),
{}
);
console.log(res);
const keys = [...new Set(data.map(item => item._id))];
const newObj = keys.reduce((acc, curr) => {
const value = data.filter(({ _id }) => _id === curr).map(({ category }) => {
return {
...category[0][0]
}
});
return {
...acc,
[curr]: value
}
}, {});
I have Object which look like
list:{
dynamicPerson: [
0: {
name:"Andrew",
company:"xCompany"
},
1: {
name:"Joseph",
company:"zCompany"
}
]
dynamicPerson2: [
0: {
name:"Andrew",
company:"xCompany"
},
1: {
name:"Joseph",
company:"zCompany"
}
]
}
I want it like
List:[
0: {
name:"Andrew",
company:"xCompany"
},
1: {
name:"Joseph",
company:"zCompany"
},
2: {
name:"Andrew",
company:"xCompany"
},
3: {
name:"Joseph",
company:"zCompany"
}
]
Note DynamicPerson is run time generated key.
You can iterate trought the keys of the object. Map the arrays to an array of array and then flatten it.
let flattened = Object.keys(list).map(key => list[key]).flat();
I modified your input slightly, because it was not syntactically right.
let list = {
dynamicPerson: [
{
name: "Andrew",
company: "xCompany"
},
{
name: "Joseph",
company: "zCompany"
}
],
dynamicPerson2: [
{
name: "Andrew",
company: "xCompany"
},
{
name: "Joseph",
company: "zCompany"
}
]
};
let flattened = Object.keys(list)
.map(key => list[key])
.flat();
console.log(flattened);
You'll find it yourself by looking for: convert object to array-of-key-value-pairs
But maybe look at the snipped in here: how-to-convert-an-object-to-an-array-of-key-value-pairs can help you
You can use flatMap():
Object.values(list).flatMap(s => s);
An example:
let list ={
dynamicPerson: [
{
name:"Andrew",
company:"xCompany"
},
{
name:"Joseph",
company:"zCompany"
}
]
, dynamicPerson2: [
{
name:"Andrew",
company:"xCompany"
},
{
name:"Joseph",
company:"zCompany"
}
]
}
const result = Object.values(list).flatMap(s => s);
console.log(result);
You can also use Object.values() and flat:
let list = {
dynamicPerson: [{
name: "Andrew",
company: "xCompany"
},
{
name: "Joseph",
company: "zCompany"
}
],
dynamicPerson2: [{
name: "Andrew",
company: "xCompany"
},
{
name: "Joseph",
company: "zCompany"
}
]
}
let List = Object.values(list).flat();
console.log(List);
I wrote a simple algo whose job is to find the corresponding name where the profession is teacher.
The given code calls the function recursively until the given result is achieved.
On executing the code, I am getting the final output is undefined. where as I was expecting the name to be ishan.
Can someone help me in diagnosing the problem in my algo?
//Accessing infitely nested Array
// Infinitely nested Array
const infiniteArray = [
{
name: "Jack",
age: "98",
profession: "doctor",
children: [
{
name: "Varun",
age: "80",
profession: "scientist",
children: [
{
name: "Ishan",
age: "62",
profession: "teacher"
}
]
}
]
}
];
const accessNestedObject = (infiniteArray) => {
return infiniteArray.forEach(element => {
if (element['profession'] === 'teacher') {
console.log(element.name)
return element.name
} else {
console.log(element["children"])
return accessNestedObject(element["children"])
}
});
}
const result = accessNestedObject(infiniteArray)
console.log(result)
You are getting undefined because that's the expected return value of Array#forEach.
You have to declare a variable that will store the final result of your loop.
//Accessing infitely nested Array
// Infinitely nested Array
const infiniteArray = [
{
name: "Jack",
age: "98",
profession: "doctor",
children: [
{
name: "Varun",
age: "80",
profession: "scientist",
children: [
{
name: "Ishan",
age: "62",
profession: "teacher"
}
]
}
]
}
];
const accessNestedObject = (infiniteArray) => {
let result = null;
infiniteArray.forEach(element => {
if (element.profession === 'teacher') {
result = element.name;
} else {
result = accessNestedObject(element.children);
}
});
return result;
}
const result = accessNestedObject(infiniteArray);
console.log(result);