let inputArr = [{
"gender": "MALE",
"name": "A",
"age": 20
},
{
"gender": "MALE",
"name": "B",
"age": 12
},
{
"gender": "FEMALE",
"name": "C",
"age": 16
},
{
"gender": "MALE",
"name": "D",
"age": 21
},
{
"gender": "FEMALE",
"name": "E",
"age": 30
}
]
console.log(JSON.stringify(inputArr.reduce((acc, ele) => {
if (acc[ele["gender"]]) {
acc[ele.gender].members.push(ele);
} else {
acc[ele["gender"]] = {
members: []
}
}
return acc;
}, {})))
I am trying to group users on the basis of gender ,using Array.reduce but the output is not showing all the records that are included in the array ,I am not able to understand the isssue here
Your reducer doesn't push the element when it encounter a gender for the first time, so the first user of each gender is missing from your result
let inputArr = [{"gender": "MALE","name": "A","age": 20},{"gender": "MALE","name": "B","age": 12},{"gender": "FEMALE","name": "C","age": 16},{"gender": "MALE","name": "D","age": 21},{"gender": "FEMALE","name": "E","age": 30}]
console.log(JSON.stringify(inputArr.reduce((acc, ele) => {
if (acc[ele["gender"]]) {
acc[ele.gender].members.push(ele);
} else {
acc[ele["gender"]] = {
members: [ele] // initialise the array with the current user
}
}
return acc;
}, {})))
Another solution, but I don't recommend this if performance matter.
let inputArr = [{
"gender": "MALE",
"name": "A",
"age": 20
},
{
"gender": "MALE",
"name": "B",
"age": 12
},
{
"gender": "FEMALE",
"name": "C",
"age": 16
},
{
"gender": "MALE",
"name": "D",
"age": 21
},
{
"gender": "FEMALE",
"name": "E",
"age": 30
}
]
function groupBy(array, field) {
return array.reduce((acc, item) => ({
...acc,
[item[field]]: [...acc[item[field]] || [], item]
}), {})
}
console.log(groupBy(inputArr, "gender"))
Related
Please how can I make this work on mongoDB.
For each item in an array, fetch data which contains the item from another collection.
For example:
"users" : [{
"name": "John doe",
"age": 51
},
{
"name": "Jake kim",
"age": 50
},
{
"name": "Jim son",
"age": 51
}]
On another collection I have
"age": [50,51,52,53,54]
Now my desire result is
"50" : [{
"name": "Jake kim",
"age": 50
}],
"51" : [{
"name": "John doe",
"age": 51
},
{
"name": "Jim son",
"age": 51
}]
You can do this. Get the array of users.
const users = [{ "name": "John doe", "age": 51 }, { "name": "Jake kim", "age": 50 }, { "name": "Jim son", "age": 51 }]
Get the array of ages
const age = [50,51,52,53,54]
Then you can map through the array of ages, returning an object that has the user that has the same age, here is the algorithm.
const mapped = age.map(age => {
const user = {}
user[age] = users.find(ob => ob.age === age);
return user;
})
If you print out the mapped result. This is what it will look like, For the ages that we couldn't find their users, they just have an undefined value.
console.log(mapped)
[
{ '50': { name: 'Jake kim', age: 50 } },
{ '51': { name: 'John doe', age: 51 } },
{ '52': undefined },
{ '53': undefined },
{ '54': undefined }
]
I don't think you'll need the age data in your case. However I've provided the both versions which one use the age list but other does not. Please find them below.
const users = [{ "name": "John doe", "age": 51 }, { "name": "Jake kim", "age": 50 }, { "name": "Jim son", "age": 51 }];
const age = [50, 51, 52, 53, 54];
const desired = users.reduce((prev, cur) => {
(prev[cur.age] ?? (prev[cur.age] = [])).push(cur);
return prev;
}, {});
console.log("This is the expected result", desired);
const desired2 = users.reduce((prev, cur) => {
(prev[cur.age] ?? (prev[cur.age] = [])).push(cur);
return prev;
}, age.reduce((prev, cur) => {
prev[cur] = [];
return prev;
}, {}));
console.log("This is the expected result with empty ages", desired2);
This is my array:
const array = [
{
"fare": "399.00",
"passenger": {
"age": "21",
"gender": "MALE",
"name": "Test1"
},
},
{
"fare": "399.00",
"passenger": {
"age": "21",
"gender": "FEMALE",
"name": "Test2"
},
}
]
How to map the object inside the array, and how to convert the object to the required output
Required output:
Test1(M), Test2(F)
Above contains "name" and gender - if its male then just "M" and if its female just "F"
As of now i tried,
array.map(o => ({ name: o.passenger.name, gender: o.passenger.gender })))
But how to convert this as expected output !
Like this
const array = [{ "fare": "399.00", "passenger": { "age": "21", "gender": "MALE", "name": "Test1" }, }, { "fare": "399.00", "passenger": { "age": "21", "gender": "FEMALE", "name": "Test2" }, } ];
const output = array
.map(({passenger}) => `${passenger.name}(${passenger.gender.slice(0,1)})`)
.join(", ")
console.log(output);
Simply loop your array and make new string:
const array = [
{
"fare": "399.00",
"passenger": {
"age": "21",
"gender": "MALE",
"name": "Test1"
},
},
{
"fare": "399.00",
"passenger": {
"age": "21",
"gender": "FEMALE",
"name": "Test2"
},
}
];
var states = array.map((o) => o.passenger.name + '(' + o.passenger.gender.substring(0, 1) + ')')
console.log(states);
Is this the expected result you want?
const array = [{
"fare": "399.00",
"passenger": {
"age": "21",
"gender": "MALE",
"name": "Test1"
},
}, {
"fare": "399.00",
"passenger": {
"age": "21",
"gender": "FEMALE",
"name": "Test2"
},
}]
const passengers = array.map(o => {
const gender = o.passenger.gender == 'MALE' ? 'M' : 'F';
return o.passenger.name + '(' + gender + ')';
})
console.log(passengers.join(', ')); // Test1(M), Test2(F)
You can convert the objects to strings and join them
const array = [{ "fare": "399.00", "passenger": { "age": "21", "gender": "MALE", "name": "Test1" }, }, { "fare": "399.00", "passenger": { "age": "21", "gender": "FEMALE", "name": "Test2" }, } ]
const output = array.map(o => o.passenger.name + (o.passenger.gender === "MALE" ? "(M)" : "(F)")).join(', ')
console.log(output)
Use map and destructruing
const tests = (arr) =>
arr
.map(
({
passenger: {
gender: [G],
name,
},
}) => `${name}(${G})`
)
.join(", ");
const array = [
{
fare: "399.00",
passenger: {
age: "21",
gender: "MALE",
name: "Test1",
},
},
{
fare: "399.00",
passenger: {
age: "21",
gender: "FEMALE",
name: "Test2",
},
},
];
console.log(tests(array));
I am looking for a way to transform JSON data into a flat "csv-like" data object. In some way, I am looking to "sqlirize" a mongodb collection. I have already check some json flat libraries in NPM but non of them quite solve my problem. I have solved it in my own way but wanted to know if there is a more efficient way.
I have a collection that presents the data through an API in the following way:
[{
"data": {
"name": "John",
"age": 23,
"friends": [{
"name": "Arya",
"age": 18,
"gender": "female"
}, {
"name": "Sansa",
"age": 20,
"gender": "female"
}, {
"name": "Bran",
"age": 17,
"gender": "male"
}]
}
}, {
"data": {
"name": "Daenerys",
"age": 24,
"friends": [{
"name": "Grey Worm",
"age": 20,
"gender": "male"
}, {
"name": "Missandei",
"age": 17,
"gender": "female"
}]
}
}]
This is the function that I have created to reflat a safe-flattened json (e.i.: everything is flattened except arrays)
const { cloneDeep } = require('lodash')
const flatten = require('flat')
const reflatten = (items) => {
const reflatted = []
items.forEach(item => {
let array = false
for (const key of Object.keys(item)) {
if (Array.isArray(item[key])) {
array = true
const children = Array(item[key].length).fill().map(() => cloneDeep(item))
for (let i = 0; i < children.length; i++) {
const keys = Object.keys(children[i][key][i])
keys.forEach(k => {
children[i][`${key}.${k}`] = children[i][key][i][k]
})
delete children[i][key]
reflatted.push(children[i])
}
break
}
}
if (!array) {
reflatted.push(item)
}
})
return reflatted.length === items.length
? reflatted
: reflatten(reflatted)
}
const rows = []
for (const item of items) {
const flat = [flatten(item)]
rows.push(...reflatten(flat)]
}
console.log(rows)
The expected (and current) output is the following:
[{
"data.name": "John",
"data.age": 23,
"data.friends.name": "Arya",
"data.friends.age": 18,
"data.friends.gender": "female"
}, {
"data.name": "John",
"data.age": 23,
"data.friends.name": "Sansa",
"data.friends.age": 20,
"data.friends.gender": "female"
}, {
"data.name": "John",
"data.age": 23,
"data.friends.name": "Bran",
"data.friends.age": 17,
"data.friends.gender": "male"
}, {
"data.name": "Daenerys",
"data.age": 24,
"data.friends.name": "Grey Worm",
"data.friends.age": 20,
"data.friends.gender": "male"
}, {
"data.name": "Daenerys",
"data.age": 24,
"data.friends.name": "Missandei",
"data.friends.age": 17,
"data.friends.gender": "female"
}]
Although I achieved the expected output, I keep wondering if there are other libraries there or if there is a more efficient way of doing it.
I would like to know if it is possible from an array of objects to retrieve several unique values with the method array.from new set.
For example :
this.data = [
{
"_id": "5bf57b965401169dd81c2a51",
"age": 35,
"name": "Paige Zamora",
"gender": "female",
"company": "AUTOMON",
"reference_id": "12"
},
{
"_id": "5bf57b96c2c3b88adff4b972",
"age": 40,
"name": "Jennifer Carr",
"gender": "female",
"company": "SYNKGEN",
"reference_id": "11"
},
{
"_id": "5bf57b969dd839926db78767",
"age": 38,
"name": "Weaver Rosales",
"gender": "male",
"company": "ETERNIS",
"reference_id": "10"
},
{
"_id": "5bf57b968c845ea691e76c84",
"age": 31,
"name": "Myers Pickett",
"gender": "male",
"company": "ETERNIS",
"reference_id": "10"
},
{
"_id": "5bf57b96998c44eff083d3fa",
"age": 36,
"name": "Dona Nicholson",
"gender": "female",
"company": "ETERNIS",
"reference_id": "10"
}
]
I would like to retrieve the following unique values: reference_id and the company associated with the reference_id, which would give this:
[{12, AUTOMON}, {11, SYNKGEN}, {10, ETERNIS}]
I thought I would use this method:
const list = Array.from (new Set (this.data.map ({reference_id}) => reference_id)));
what returns :
[12,11,10]
I do not know if this method can be used to return multiple values like the list above ?
You could use a JSON with the wanted data and take then the parsed values as result.
Why a string instead of an object, you may ask. The problem here is every new object with the wanted properties is a new object, and not the same.
Set works wite a single primitive or object and checks, if an object's reference is the same. By taking a string, the value could be checked and you get unique strings in the set. This required to convert the JSON back to an object.
var data = [{ _id: "5bf57b965401169dd81c2a51", age: 35, name: "Paige Zamora", gender: "female", company: "AUTOMON", reference_id: "12" }, { _id: "5bf57b96c2c3b88adff4b972", age: 40, name: "Jennifer Carr", gender: "female", company: "SYNKGEN", reference_id: "11" }, { _id: "5bf57b969dd839926db78767", age: 38, name: "Weaver Rosales", gender: "male", company: "ETERNIS", reference_id: "10" }, { _id: "5bf57b968c845ea691e76c84", age: 31, name: "Myers Pickett", gender: "male", company: "ETERNIS", reference_id: "10" }, { _id: "5bf57b96998c44eff083d3fa", age: 36, name: "Dona Nicholson", gender: "female", company: "ETERNIS", reference_id: "10" }],
unique = Array.from(
new Set(
data.map(({ reference_id, company }) =>
JSON.stringify({ reference_id, company }))
),
json => JSON.parse(json)
);
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can also group them in a Map (ignoring any repetitions and where keys are the string representations of reference_id and company) and return an array from its values:
var data = [{
"_id": "5bf57b965401169dd81c2a51",
"age": 35,
"name": "Paige Zamora",
"gender": "female",
"company": "AUTOMON",
"reference_id": "12"
},
{
"_id": "5bf57b96c2c3b88adff4b972",
"age": 40,
"name": "Jennifer Carr",
"gender": "female",
"company": "SYNKGEN",
"reference_id": "11"
},
{
"_id": "5bf57b969dd839926db78767",
"age": 38,
"name": "Weaver Rosales",
"gender": "male",
"company": "ETERNIS",
"reference_id": "10"
},
{
"_id": "5bf57b968c845ea691e76c84",
"age": 31,
"name": "Myers Pickett",
"gender": "male",
"company": "ETERNIS",
"reference_id": "10"
},
{
"_id": "5bf57b96998c44eff083d3fa",
"age": 36,
"name": "Dona Nicholson",
"gender": "female",
"company": "ETERNIS",
"reference_id": "10"
}
];
var res = Array.from(data.reduce((acc, {reference_id, company}) => {
acc.set(`${reference_id},${company}`, {reference_id, company});
return acc;
}, new Map()).values());
console.log(res);
Try this:
this.data.map((el) =>{ return {age: el.age, company: el.company} })
// You get this array
//0: {age: 35, company: "AUTOMON"}
//1: {age: 40, company: "SYNKGEN"}
//2: {age: 38, company: "ETERNIS"}
//3: {age: 31, company: "ETERNIS"}
//4: {age: 36, company: "ETERNIS"}
{12, AUTOMON} doesn't make sense, obj is { key: value, key: value...}
I have and object db_parsed
when I run console.log(JSON.stringify(db_parsed, null, 4))
the result is:
{
"data": [
[
{
"name": "Me",
"age": 23,
"sex": "M"
},
{
"name": "Wonderwoman",
"age": 22,
"sex": "F"
}
],
[
{
"name": "ALbert The Man",
"age": 22,
"sex": "M"
}
],
[
{
"name": "Leonard Johnson",
"age": 23,
"sex": "M"
}
]
]
}
but when I run console.log(db_parsed.data.filter(obj => obj.age === 22))
the result is []
Why? What am i missing? How do I fix this?
db_parsed.data is an array containing arrays.
That second level of arrays contains objects.
Your filter code is trying to treat those objects and being directly inside db_parsed.data instead of inside db_parsed.data[0], db_parsed.data[1] and db_parsed.data[2].
You could use reduce to concatenate all the second level of arrays into one, and then filter on that.
var db_parsed = {
"data": [
[{
"name": "Me",
"age": 23,
"sex": "M"
},
{
"name": "Wonderwoman",
"age": 22,
"sex": "F"
}
],
[{
"name": "ALbert The Man",
"age": 22,
"sex": "M"
}],
[{
"name": "Leonard Johnson",
"age": 23,
"sex": "M"
}]
]
};
console.log(db_parsed.data.reduce((a,b) => a.concat(b), []).filter(obj => obj.age === 22))
You can do [].concat.apply([], db_parsed.data) and than filter the array of objects:
const db_parsed = {"data": [[{"name": "Me","age": 23,"sex": "M"},{"name": "Wonderwoman","age": 22,"sex": "F"}],[{"name": "ALbert The Man","age": 22,"sex": "M"}],[{"name": "Leonard Johnson","age": 23,"sex": "M"}]]};
const result = [].concat.apply([], db_parsed.data).filter(obj => obj.age === 22);
console.log(result);