i am using angular 4 for one of my projects and i have a situation where i have to group the data based on multiple conditions as explained below.
Raw data
[
{
age: "12",
details: [
{
address: "street1"
}
]
},
{
age: "12",
details: [
{
address: "street2"
}
]
},
{
age: "12",
details: [
{
address: "street1"
}
]
}]
I want to group data based on both age and address field so the result would be something like
{
stree1: [{
age: "12",
details: [
{
address: "street1"
}
]
}, {
age: "12",
details: [
{
address: "street1"
}
]
}
],
street2: [{
age: "12",
details: [
{
address: "street1"
}
]
}]
}
I know we can use lodash to group the data based on single condition like
_.groupBy(data, 'age');
But i am not understanding how to do this based on multiple conditions. I want to group all those objects which has same address and same age. Something like
_.groupBy(data, 'age' && details[0].address);
How to go about this. Please help.
If you are sure that your object structure will be exactly the same always and will have only one object in details then you can directly do Stringify to identify the combo, if your object have several data, then you can create a new object {age: value, street: value} and stringify it to identify the combo. However I will strongly suggest not to use any pipe or anything as deliminator, and joining them to create unique combination of string to find a group. Sometimes that can spoil your value.
Here is what you need:
_(rawData).groupBy(JSON.stringify).filter(arr=>arr.length>1).mapKeys(v=>v[0].details[0].address).value()
Here is an working example:
var rawData = [
{
age: "12",
details: [
{
address: "street1"
}
]
},
{
age: "12",
details: [
{
address: "street2"
}
]
},
{
age: "12",
details: [
{
address: "street1"
}
]
}];
var result = _(rawData)
.groupBy(JSON.stringify)
.filter(arr=>arr.length>1)
.mapKeys(v=>v[0].details[0].address)
.value();
console.log('Expected result: ', result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Here is what you do if there can be multiple other things in your object
var rawData = [
{
age: "12",
details: [
{
address: "street1"
}
]
},
{
age: "12",
details: [
{
address: "street2"
}
]
},
{
age: "12",
details: [
{
address: "street1"
}
]
}];
var result = _(rawData)
.groupBy(obj=>JSON.stringify({age: obj.age, address: obj.details[0].address}))
.filter(arr=>arr.length>1)
.mapKeys(v=>v[0].details[0].address)
.value();
console.log('Expected result: ', result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
something like:
const res = _.chain(arr)
.groupBy('age')
.mapValues(ageArr => _.groupBy(ageArr, ageObj => ageObj.details[0].address))
.value();
Related
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 an array of objects which looks like
const test = [{client: {id: "1", "Name": "peter" , marks: { subject: { english : 10 } } }, {door: {id: "2", "Name": "parker" , marks: { subject: { French : 13 } } }]
Now, In this array of object I have two objects and their keys are , client and door . now,
I want to destructure it like,
const [firstobj, secondObj ] = test.forEach(() -> {})
is there any way though which I can do it,
one solution is like test[0].Client , but is there another solution for this ?
Thanks.
You can do pretty much like you had:
const [first, second] = test;
const test = [
{ client: { id: "1", Name: "peter", marks: { subject: { english: 10 } } } },
{ door: { id: "2", Name: "parker", marks: { subject: { French: 13 } } } },
];
const [first, second] = test;
console.log(first.client);
console.log(second.door);
I want to convert or transform an object to the other object, which I want to.
inout object looks like that:
[
{0: {contact: {
1: {
name: abc,
address: street
},
2: {
name: kdf,
address: streedsd
}
}
}
}
{4: {education: {
0: {
uni: ssdabc,
address: street
},
1: {
uni: sdaskdf,
address: streedsd
}
}
}
}
]
what I expeced is:
[
{contact: [
{
name: abc,
address: street
},
{
name: kdf,
address: streedsd
}
]
}
{education: {
[ {
name: abc,
address: street
},
{
name: kdf,
address: streedsd
}
]
}
]
any solutions??? for the best, need a dynamic method, not only for contact.
this input object will be generated dynamically.
You can use Array.map() to iterate over the outer array and Object.values() to get values as array for the contact property.
const data = [{
contact: {
0: {
name: 'abc',
address: 'street'
},
1: {
name: 'kdf',
address: 'streedsd'
}
}
},
{
education: {
0: {
uni: 'ssdabc',
address: 'street'
},
1: {
uni: 'sdaskdf',
address: 'streedsd'
}
}
}
]
const convertedData = data.map(datum => {
Object.keys(datum).forEach(key => {
datum[key] = Object.values(datum[key])
})
return datum;
})
console.log('Converted Data:',convertedData)
console.log('Original Data:', data)
Important
Be aware that this method modifies the original data. If you don't want to modify the original, you can use Array.reduce() instead of Array.map()
You can use Object.values to extract the values of an object into a list.
Here is a code snippet that applies that to each item in your input:
(Various changes have been made to input and outputs in the question, some of them are invalid json but this works for a fixed version of the latest edit)
const input = [{
contact: {
0: {
name: "abc",
address: "street"
},
1: {
name: "kdf",
address: "streedsd"
}
}
}, {
education: {
0: {
uni: "ssdabc",
address: "street"
},
1: {
uni: "sdaskdf",
address: "streedsd"
}
}
}]
const output = input.map(item => Object.entries(item).map(([key, value]) => ({
[key]: Object.values(value)
})))
console.log(output)
I have this object inside a json:
{
"group": "A",
"id": "50"
"person": [
{
"name": 'Joe',
"age": '29'
"hobbies": ["Watching movies", "Gaming"]
},
{
"name": 'Jessie',
"age": '27'
"hobbies": ["Gaming", "Reading"]
}
]
}
I want to filter the people by their hobbies. For example, if I filter by Gaming I need to create an array of objects with Joe and Jessie. If I filter by Reading, then the array would only have Jessie.
Here is my code:
import { people } from '../../../data/index' // this is the json I shower above
let filteredArray;
filteredArray = people.filter(person => {
return person.hobbies == "Gaming";
})
this doesn't work, but if change the hobbies to a single word on the json, like this:
{
"name": 'Jessie',
"age": '27'
"hobbies": "Gaming"
}
then it work just fine.
So is there a way to use filter with a array of hobbies to check if one of the values match my condition?
I'm using only vanilla Js and I only want to support chrome.
Sorry for any english mistake or if the question is not clear enought, I'm still in the beggining of my studies
You have to use includes method. Because you are trying to search in array:
const filteredArray = people.filter(person => {
return person.hobbies.includes("Gaming");
})
const data = {
group: 'A',
id: '50',
person: [
{
name: 'Joe',
age: '29',
hobbies: ['Watching movies', 'Gaming']
},
{
name: 'Jessie',
age: '27',
hobbies: ['Gaming', 'Reading']
}
]
};
const result = data.person.filter(el => el.hobbies.includes('Gaming'));
console.log(result);
I am getting below JSON response:
users: {
1: {
name: "John",
email: "john#test.com",
id: 1,
place: "NY"
},
2: {
name: "Alex",
email: "alex#test.com",
id: 2,
place: "FL"
},
3: {
name: "Tony",
email: "tony#test.com",
id: 3,
place: "TX"
}
.
.
.
.
.
.
}
I want to swap the id key with email key from the inner object value as below format.
users: {
"john#test.com": {
name: "John",
email: "john#test.com",
id: 1,
place: "NY"
},
}
I am using below lodash code to make it work and its working fine:
_.keyBy(_.values(data), 'email');
Is there a better way I can handle it with lodash? I am new to lodash and I wanted to understand whether the code can be refactored further.
See _.keyBy() accepts a collection (an array or an object), you can skip the _.values() call:
const users = {"1":{"name":"John","email":"john#test.com","id":1,"place":"NY"},"2":{"name":"Alex","email":"alex#test.com","id":2,"place":"FL"},"3":{"name":"Tony","email":"tony#test.com","id":3,"place":"TX"}};
const result = _.keyBy(users, 'email');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
If you are looking for Vanilla JavaScript solution you can use array#reduce like this:
users = {
1: {
name: "John",
email: "john#test.com",
id: 1,
place: "NY"
},
2: {
name: "Alex",
email: "alex#test.com",
id: 2,
place: "FL"
},
3: {
name: "Tony",
email: "tony#test.com",
id: 3,
place: "TX"
}
}
let newUsers = Object.keys(users).reduce((obj, key) => {
obj[users[key].email] = users[key];
return obj;
}, {});
console.log(newUsers);