Javascript sort obj by compound key - javascript

I have an object so defined:
{
_id: "5d406a171ed43384972f04b5",
index: 0,
age: 28,
eyeColor: "brown",
name: {
first: "Myra",
last: "Navarro"
},
company: "SUSTENZA",
email: "myra.navarro#sustenza.net"
}
I would need to be able to do the search on all keys, even in compound keys like name.
For example I have a search string name.first and the like, it could be even deeper and compound objects.
I managed to do this, but on name.first for example I am failing to get it to work.
Can you give me a hand?
let datatable = [
{
_id: "5d406a171ed43384972f04b5",
index: 0,
age: 28,
eyeColor: "brown",
name: {
first: "Myra",
last: "Navarro"
},
company: "SUSTENZA",
email: "myra.navarro#sustenza.net"
},
{
_id: "5d406a170db0f4b04d9a9acf",
index: 1,
age: 23,
eyeColor: "blue",
name: {
first: "Harriett",
last: "Tanner"
},
company: "VALPREAL",
email: "harriett.tanner#valpreal.com"
},
{
_id: "5d406a17e95da8ff80a759c5",
index: 2,
age: 39,
eyeColor: "blue",
name: {
first: "Vega",
last: "Hanson"
},
company: "BEDLAM",
email: "vega.hanson#bedlam.tv"
},
{
_id: "5d406a175505da190e6875ec",
index: 3,
age: 31,
eyeColor: "blue",
name: {
first: "Rosemary",
last: "Fields"
},
company: "QUAILCOM",
email: "rosemary.fields#quailcom.me"
},
{
_id: "5d406a17ea96044c027f4e50",
index: 4,
age: 27,
eyeColor: "brown",
name: {
first: "Dale",
last: "Wilkinson"
},
company: "QIAO",
email: "dale.wilkinson#qiao.org"
},
{
_id: "5d406a17c5fff1ff6653a555",
index: 5,
age: 25,
eyeColor: "blue",
name: {
first: "Beatrice",
last: "Contreras"
},
company: "ZENOLUX",
email: "beatrice.contreras#zenolux.us"
},
{
_id: "5d406a17a199efcba25e1f26",
index: 6,
age: 34,
eyeColor: "blue",
name: {
first: "Hancock",
last: "Wynn"
},
company: "PLASMOS",
email: "hancock.wynn#plasmos.co.uk"
},
{
_id: "5d406a17019a2a4544a4f134",
index: 7,
age: 40,
eyeColor: "blue",
name: {
first: "Brown",
last: "Stanton"
},
company: "SNACKTION",
email: "brown.stanton#snacktion.name"
},
{
_id: "5d406a17e516dd71af8210d4",
index: 8,
age: 39,
eyeColor: "blue",
name: {
first: "Barnes",
last: "Dunn"
},
company: "PORTALINE",
email: "barnes.dunn#portaline.ca"
},
{
_id: "5d406a17516936a025b73c33",
index: 9,
age: 34,
eyeColor: "green",
name: {
first: "Blanche",
last: "Cherry"
},
company: "ISOSWITCH",
email: "blanche.cherry#isoswitch.io"
},
{
_id: "5d406a17527a4d2c6a7897dd",
index: 10,
age: 33,
eyeColor: "blue",
name: {
first: "Gilliam",
last: "Farley"
},
company: "AMTAS",
email: "gilliam.farley#amtas.biz"
},
{
_id: "5d406a175ff11478c416c30b",
index: 11,
age: 26,
eyeColor: "brown",
name: {
first: "Laura",
last: "Short"
},
company: "FISHLAND",
email: "laura.short#fishland.info"
},
{
_id: "5d406a1738181b471847339a",
index: 12,
age: 20,
eyeColor: "brown",
name: {
first: "Moreno",
last: "Barber"
},
company: "KEENGEN",
email: "moreno.barber#keengen.net"
},
{
_id: "5d406a17a6bcae6fe3ad1735",
index: 13,
age: 30,
eyeColor: "brown",
name: {
first: "Fischer",
last: "French"
},
company: "INCUBUS",
email: "fischer.french#incubus.com"
},
{
_id: "5d406a17600ca53e8f63f263",
index: 14,
age: 30,
eyeColor: "brown",
name: {
first: "Donaldson",
last: "Carr"
},
company: "SUNCLIPSE",
email: "donaldson.carr#sunclipse.tv"
},
{
_id: "5d406a17530655789a27174f",
index: 15,
age: 35,
eyeColor: "green",
name: {
first: "Sophia",
last: "Payne"
},
company: "PRISMATIC",
email: "sophia.payne#prismatic.me"
},
{
_id: "5d406a175dbc687b4c7669d8",
index: 16,
age: 34,
eyeColor: "green",
name: {
first: "Simone",
last: "Pollard"
},
company: "DIGIGEN",
email: "simone.pollard#digigen.org"
},
{
_id: "5d406a179f35ed326a6a5567",
index: 17,
age: 28,
eyeColor: "green",
name: {
first: "Yvette",
last: "Daugherty"
},
company: "CHILLIUM",
email: "yvette.daugherty#chillium.us"
}
];
const sortAsc = true;
const sortField = "name.first";//index,eyeColor
var result = datatable.sort((a, b) => {
let [x, z] = sortAsc ? [a, b] : [b, a];
//console.log(x[sortField], z[sortField], x[sortField] > z[sortField] ? 1 : -1);
return x[sortField] > z[sortField] ? 1 : -1;
});
console.log(result);
Edit:
It seems to work like this, but I would like to write it in a more compact form and possibly reduce the computation time.
Do you think it is possible?
var result = datatable.sort((a, b) => {
let [x, z] = sortAsc ? [a, b] : [b, a];
const arraySplit = sortField.split('.');
var vX = arraySplit.reduce((a, b) => a[b], x);
var vZ = arraySplit.reduce((a, b) => a[b], z);
return vX > vZ ? 1 : -1;
});

First issue is that javascript doesn't automatically access children using dots.
If you want to implement that, here are some solutions:
Access object child properties using a dot notation string
Next, once you have the value you want to compare with.
You need to use a special string compare function if the value is a string (use typeof to check). Or use valA - valB so that you get 1, 0, and -1 as the return values to sort with.

I hope this is what you need. The child function makes what you need. You have the explanation in the comments.
let datatable = [
{
_id: "5d406a171ed43384972f04b5",
index: 0,
age: 28,
eyeColor: "brown",
name: {
first: "Myra",
last: "Navarro"
},
company: "SUSTENZA",
email: "myra.navarro#sustenza.net"
},
{
_id: "5d406a170db0f4b04d9a9acf",
index: 1,
age: 23,
eyeColor: "blue",
name: {
first: "Harriett",
last: "Tanner"
},
company: "VALPREAL",
email: "harriett.tanner#valpreal.com"
},
{
_id: "5d406a17e95da8ff80a759c5",
index: 2,
age: 39,
eyeColor: "blue",
name: {
first: "Vega",
last: "Hanson"
},
company: "BEDLAM",
email: "vega.hanson#bedlam.tv"
},
{
_id: "5d406a175505da190e6875ec",
index: 3,
age: 31,
eyeColor: "blue",
name: {
first: "Rosemary",
last: "Fields"
},
company: "QUAILCOM",
email: "rosemary.fields#quailcom.me"
},
{
_id: "5d406a17ea96044c027f4e50",
index: 4,
age: 27,
eyeColor: "brown",
name: {
first: "Dale",
last: "Wilkinson"
},
company: "QIAO",
email: "dale.wilkinson#qiao.org"
},
{
_id: "5d406a17c5fff1ff6653a555",
index: 5,
age: 25,
eyeColor: "blue",
name: {
first: "Beatrice",
last: "Contreras"
},
company: "ZENOLUX",
email: "beatrice.contreras#zenolux.us"
},
{
_id: "5d406a17a199efcba25e1f26",
index: 6,
age: 34,
eyeColor: "blue",
name: {
first: "Hancock",
last: "Wynn"
},
company: "PLASMOS",
email: "hancock.wynn#plasmos.co.uk"
},
{
_id: "5d406a17019a2a4544a4f134",
index: 7,
age: 40,
eyeColor: "blue",
name: {
first: "Brown",
last: "Stanton"
},
company: "SNACKTION",
email: "brown.stanton#snacktion.name"
},
{
_id: "5d406a17e516dd71af8210d4",
index: 8,
age: 39,
eyeColor: "blue",
name: {
first: "Barnes",
last: "Dunn"
},
company: "PORTALINE",
email: "barnes.dunn#portaline.ca"
},
{
_id: "5d406a17516936a025b73c33",
index: 9,
age: 34,
eyeColor: "green",
name: {
first: "Blanche",
last: "Cherry"
},
company: "ISOSWITCH",
email: "blanche.cherry#isoswitch.io"
},
{
_id: "5d406a17527a4d2c6a7897dd",
index: 10,
age: 33,
eyeColor: "blue",
name: {
first: "Gilliam",
last: "Farley"
},
company: "AMTAS",
email: "gilliam.farley#amtas.biz"
},
{
_id: "5d406a175ff11478c416c30b",
index: 11,
age: 26,
eyeColor: "brown",
name: {
first: "Laura",
last: "Short"
},
company: "FISHLAND",
email: "laura.short#fishland.info"
},
{
_id: "5d406a1738181b471847339a",
index: 12,
age: 20,
eyeColor: "brown",
name: {
first: "Moreno",
last: "Barber"
},
company: "KEENGEN",
email: "moreno.barber#keengen.net"
},
{
_id: "5d406a17a6bcae6fe3ad1735",
index: 13,
age: 30,
eyeColor: "brown",
name: {
first: "Fischer",
last: "French"
},
company: "INCUBUS",
email: "fischer.french#incubus.com"
},
{
_id: "5d406a17600ca53e8f63f263",
index: 14,
age: 30,
eyeColor: "brown",
name: {
first: "Donaldson",
last: "Carr"
},
company: "SUNCLIPSE",
email: "donaldson.carr#sunclipse.tv"
},
{
_id: "5d406a17530655789a27174f",
index: 15,
age: 35,
eyeColor: "green",
name: {
first: "Sophia",
last: "Payne"
},
company: "PRISMATIC",
email: "sophia.payne#prismatic.me"
},
{
_id: "5d406a175dbc687b4c7669d8",
index: 16,
age: 34,
eyeColor: "green",
name: {
first: "Simone",
last: "Pollard"
},
company: "DIGIGEN",
email: "simone.pollard#digigen.org"
},
{
_id: "5d406a179f35ed326a6a5567",
index: 17,
age: 28,
eyeColor: "green",
name: {
first: "Yvette",
last: "Daugherty"
},
company: "CHILLIUM",
email: "yvette.daugherty#chillium.us"
}
];
const sortAsc = true;
const sortField = "name.first";//index,eyeColor
var result = datatable.sort((a, b) => {
let [x, z] = sortAsc ? [a, b] : [b, a];
//console.log(x[sortField], z[sortField], x[sortField] > z[sortField] ? 1 : -1);
//return x[sortField] > z[sortField] ? 1 : -1;
return child(x, sortField) > child(z, sortField) ? 1: -1;
});
console.log(result);
function child(obj, str){
//take dot-separated chain of properties' names and split them into an array
const props = str.split('.');
let child = obj;
//looop through all properties' names and get the access to the following [Object] children sequentially
props.forEach((prop)=> child = child[prop]);
return child;
}

Option 1:
const objRoute = sortField.split(".");
const getValue = obj => objRoute.reduce((v, c) => v[c], obj);
const result = datatable.sort((a, b) =>
sortAsc
? getValue(a).localeCompare() - getValue(b).localeCompare()
: getValue(b).localeCompare() - getValue(a).localeCompare()
);
Option 2:
Use eval, eval() evaluates the expression.
It is recommended to use this function with caution:
const result = datatable.sort((a, b, i) => eval(`a.${sortField}`) - eval(`b.${sortField}`));

Related

How to get all objects and count booleans (JS)

Let it be like this for example:
let data = {
first: {
surname: 'Miller',
age: 37,
gender: 'male',
stealer: true
},
second: {
surname: 'Connor',
age: 28,
gender: 'male',
stealer: true
},
third: {
surname: 'Smith',
age: 13,
gender: 'female',
stealer: false
}
}
How can I get everything at once and count booleans of false, without the need to manually enter each one individually?
You can use Object.values to retrieve the values as an array and Array.prototype.reduce to count:
let data = { first: { surname: 'Miller', age: 37, gender: 'male', stealer: true }, second: { surname: 'Connor', age: 28, gender: 'male', stealer: true }, third: { surname: 'Smith', age: 13, gender: 'female', stealer: false } };
const result = Object.values(data).flatMap(el => Object.values(el)).reduce((acc, el) => acc + (el === false), 0);
console.log(result);

A simple methodology to merge Array of the nested object into an array of the same object

I'm looking for a simple methodology to merge the Array of the nested object into an array of the same object
Input:
const data=[
{ id: 123, name: "dave", age: 23 , address:{city:"chennai", zipcode:600001}},
{ id: 456, name: "chris", age: 23, address:{city:"cbe", zipcode:600002} },
{ id: 789, name: "bob", age: 23, address:{city:"tiruppur", zipcode:600003}},
{ id: 101, name: "tom", age: 23, address:{city:"erode", zipcode:600004} },
{ id: 102, name: "tim", age: 23, address:{city:"selam", zipcode:600005} }
]
Needed Output:
{ id: 123, name: "dave", age: 23, city:"chennai", zipcode:600001},
{ id: 456, name: "chris", age: 23, city:"cbe", zipcode:600002},
{ id: 789, name: "bob", age: 23, city:"tiruppur", zipcode:600003},
{ id: 101, name: "tom", age: 23, city:"erode", zipcode:600004},
{ id: 102, name: "tim", age: 23, city:"selam", zipcode:600005}
]
Use a combination of destructuring and spread syntax:
const data=[{ id: 123, name: "dave", age: 23 , address:{city:"chennai", zipcode:600001}},{ id: 456, name: "chris", age: 23, address:{city:"cbe", zipcode:600002} },{ id: 789, name: "bob", age: 23, address:{city:"tiruppur", zipcode:600003}},{ id: 101, name: "tom", age: 23, address:{city:"erode", zipcode:600004} },{ id: 102, name: "tim", age: 23, address:{city:"selam", zipcode:600005} }];
const result = data.map(({address, ...rest}) => ({...rest, ...address}));
console.log(result);
You can use Object.entries to extract each property and its value in the address property and assign it to the parent object, then delete the address property.
const data=[{id:123,name:"dave",age:23,address:{city:"chennai",zipcode:600001}},{id:456,name:"chris",age:23,address:{city:"cbe",zipcode:600002}},{id:789,name:"bob",age:23,address:{city:"tiruppur",zipcode:600003}},{id:101,name:"tom",age:23,address:{city:"erode",zipcode:600004}},{id:102,name:"tim",age:23,address:{city:"selam",zipcode:600005}}];
const result = data.map(e => (Object.entries(e.address).forEach(f => e[f[0]] = f[1]), delete e.address, e))
console.log(result)
let data = [
{ id: 123, name: "dave", age: 23, address: { city: "chennai", zipcode: 600001 } },
{ id: 456, name: "chris", age: 23, address: { city: "cbe", zipcode: 600002 } },
{ id: 789, name: "bob", age: 23, address: { city: "tiruppur", zipcode: 600003 } },
{ id: 101, name: "tom", age: 23, address: { city: "erode", zipcode: 600004 } },
{ id: 102, name: "tim", age: 23, address: { city: "selam", zipcode: 600005 } }
]
data = data.map((node) => ({ id: node.id, name: node.name, age: node.age, city: node.address.city, zipcode: node.address.zipcode }))
console.log(data)
const data=[
{ id: 123, name: "dave", age: 23 , address:{city:"chennai", zipcode:600001}},
{ id: 456, name: "chris", age: 23, address:{city:"cbe", zipcode:600002} },
{ id: 789, name: "bob", age: 23, address:{city:"tiruppur", zipcode:600003}},
{ id: 101, name: "tom", age: 23, address:{city:"erode", zipcode:600004} },
{ id: 102, name: "tim", age: 23, address:{city:"selam", zipcode:600005} }
];
const result = data.map(item => ({id: item.id, name: item.name, age: item.age, ...item.address}));
console.log(result);

Js recursive function that specified attribute returns it

I am writing the following code which specified the attribute must return it even if it is of type obj, array, string or number.
I'm having some problems getting me back certain attributes going even deeper.
I would like to do this without using external modules.
Can you give me some advice?
function returnElement(obj, label) {
let pointBool = label.includes(".");
let arrayOpenBool = label.includes("[");
let arrayCloseBool = label.includes("]");
//console.log(obj, label,arrayOpenBool && arrayCloseBool);
if (arrayOpenBool && arrayCloseBool) {
let start = label.split("[")[0];
let number = label.split("[")[1].split("]")[0];
let end = label.split("]")[0];
if (label.includes(".")) end = label.split(".")[1];
return obj[start][number]
? returnElement(obj[start][number], end)
: undefined;
}
if (pointBool) {
let start = label.split(".")[0];
let end = label.split(".")[1];
//console.log(obj, label, start, end, obj[end]);
if (start === "") return obj[end];
return returnElement(obj[start], end);
}
return obj[label];
}
var a = {
_id: "5d406a179f35ed326a6a5567",
age: 28,
name: {first: "James",last: "Bond"},
user: [{first: "Jon",last: "Witch"},{first: "Myra",last: "Navarro",number:[0,10]}]
};
var b = [];
b.push("item");//undefined
b.push("_id");//5d406a179f35ed326a6a5567
b.push("age");//28
b.push("name.first");//James
b.push("user[1]");//obj{}
b.push("user[1].first");//Myra
b.push("user[2].first");//undefined
b.push("user[1].email");//undefined
b.push("user[0].number");//[0, 1]
b.push("user[1].number[1]");//1
b.forEach(el => {
console.log(returnElement(a, el));
})
Edit:
Here is an additional thing, given the solution proposed by #NinaScholz, it allows you to sort the data you more parameters, if it can be of use to someone.
based on the following solution: Link
let datatable = [
{
_id: '5d406a171ed43384972f04b5',
index: 0,
age: 28,
eyeColor: 'brown',
name: {
first: 'Myra',
last: 'Navarro',
},
company: 'SUSTENZA',
email: 'myra.navarro#sustenza.net',
},
{
_id: '5d406a170db0f4b04d9a9acf',
index: 1,
age: 23,
eyeColor: 'blue',
name: {
first: 'Harriett',
last: 'Tanner',
},
company: 'VALPREAL',
email: 'harriett.tanner#valpreal.com',
},
{
_id: '5d406a17e95da8ff80a759c5',
index: 2,
age: 39,
eyeColor: 'blue',
name: {
first: 'Vega',
last: 'Hanson',
},
company: 'BEDLAM',
email: 'vega.hanson#bedlam.tv',
},
{
_id: '5d406a175505da190e6875ec',
index: 3,
age: 31,
eyeColor: 'blue',
name: {
first: 'Rosemary',
last: 'Fields',
},
company: 'QUAILCOM',
email: 'rosemary.fields#quailcom.me',
},
{
_id: '5d406a17ea96044c027f4e50',
index: 4,
age: 27,
eyeColor: 'brown',
name: {
first: 'Dale',
last: 'Wilkinson',
},
company: 'QIAO',
email: 'dale.wilkinson#qiao.org',
},
{
_id: '5d406a17c5fff1ff6653a555',
index: 5,
age: 25,
eyeColor: 'blue',
name: {
first: 'Beatrice',
last: 'Contreras',
},
company: 'ZENOLUX',
email: 'beatrice.contreras#zenolux.us',
},
{
_id: '5d406a17a199efcba25e1f26',
index: 6,
age: 34,
eyeColor: 'blue',
name: {
first: 'Hancock',
last: 'Wynn',
},
company: 'PLASMOS',
email: 'hancock.wynn#plasmos.co.uk',
},
{
_id: '5d406a17019a2a4544a4f134',
index: 7,
age: 40,
eyeColor: 'blue',
name: {
first: 'Beatrice',
last: 'Aston',
},
company: 'SNACKTION',
email: 'beatrice.aston#snacktion.name',
},
{
_id: '5d406a17e516dd71af8210d4',
index: 8,
age: 39,
eyeColor: 'blue',
name: {
first: 'Barnes',
last: 'Dunn',
},
company: 'PORTALINE',
email: 'barnes.dunn#portaline.ca',
},
{
_id: '5d406a17516936a025b73c33',
index: 9,
age: 34,
eyeColor: 'green',
name: {
first: 'Blanche',
last: 'Cherry',
},
company: 'ISOSWITCH',
email: 'blanche.cherry#isoswitch.io',
},
{
_id: '5d406a17527a4d2c6a7897dd',
index: 10,
age: 33,
eyeColor: 'blue',
name: {
first: 'Gilliam',
last: 'Farley',
},
company: 'AMTAS',
email: 'gilliam.farley#amtas.biz',
},
{
_id: '5d406a175ff11478c416c30b',
index: 11,
age: 26,
eyeColor: 'brown',
name: {
first: 'Laura',
last: 'Short',
},
company: 'FISHLAND',
email: 'laura.short#fishland.info',
},
{
_id: '5d406a1738181b471847339a',
index: 12,
age: 20,
eyeColor: 'brown',
name: {
first: 'Moreno',
last: 'Barber',
},
company: 'KEENGEN',
email: 'moreno.barber#keengen.net',
},
{
_id: '5d406a17a6bcae6fe3ad1735',
index: 13,
age: 30,
eyeColor: 'brown',
name: {
first: 'Fischer',
last: 'French',
},
company: 'INCUBUS',
email: 'fischer.french#incubus.com',
},
{
_id: '5d406a17600ca53e8f63f263',
index: 14,
age: 30,
eyeColor: 'brown',
name: {
first: 'Donaldson',
last: 'Carr',
},
company: 'SUNCLIPSE',
email: 'donaldson.carr#sunclipse.tv',
},
{
_id: '5d406a17530655789a27174f',
index: 15,
age: 35,
eyeColor: 'green',
name: {
first: 'Sophia',
last: 'Payne',
},
company: 'PRISMATIC',
email: 'sophia.payne#prismatic.me',
},
{
_id: '5d406a175dbc687b4c7669d8',
index: 16,
age: 34,
eyeColor: 'green',
name: {
first: 'Simone',
last: 'Pollard',
},
company: 'DIGIGEN',
email: 'simone.pollard#digigen.org',
},
{
_id: '5d406a179f35ed326a6a5567',
index: 17,
age: 28,
eyeColor: 'green',
name: {
first: 'Yvette',
last: 'Daugherty',
},
company: 'CHILLIUM',
email: 'yvette.daugherty#chillium.us',
},
];
function getValue(object, path) {
return path
.replace(/\[/g, '.')
.replace(/\]/g, '')
.split('.')
.reduce((o, k) => (o || {})[k], object);
}
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
var result = (getValue(a, property) < getValue(b, property)) ? -1 : (getValue(a, property) > getValue(b, property)) ? 1 : 0;
return result * sortOrder;
}
}
function dynamicSortMultiple() {
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}
function dynamicSortMultipleRic() {
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
while(result === 0 && i < numberOfProperties) result = dynamicSort(props[i++])(obj1, obj2);
return result;
}
}
var copyA = Object.assign([], datatable);
var copyB = Object.assign([], datatable);
var copyC = Object.assign([], datatable);
let a = copyA.sort(dynamicSort("name.first"));
let b = copyB.sort(dynamicSortMultiple("name.first","name.last"));
let c = copyC.sort(dynamicSortMultipleRic("name.first","name.last"));
console.log(a,b,c)
You could replace the brackets and split the string and get the values form the given object.
function getValue(object, path) {
return path
.replace(/\[/g, '.')
.replace(/\]/g, '')
.split('.')
.reduce((o, k) => (o || {})[k], object);
}
var a = { _id: "5d406a179f35ed326a6a5567", age: 28, name: { first: "James", last: "Bond" }, user: [{ first: "Jon", last: "Witch" }, { first: "Myra", last: "Navarro", number: [0, 10] }] };
var b = [];
b.push("item");//undefined
b.push("_id");//5d406a179f35ed326a6a5567
b.push("age");//28
b.push("name.first");//James
b.push("user[1]");//obj{}
b.push("user[1].first");//Myra
b.push("user[2].first");//undefined
b.push("user[1].email");//undefined
b.push("user[1].number");//[0, 1]
b.push("user[1].number[1]");//1
b.forEach(el => {
console.log(getValue(a, el));
});
.as-console-wrapper { max-height: 100% !important; top: 0; }

Filter array and reset the index too

I have an array of objects like this:
const data = [
{
name: "Peter",
age: 20,
nationality: "American",
index: 0
},
{
name: "David",
age: 25,
nationality: "English",
index: 1
},
{
name: "Gabriel",
age: 23,
nationality: "Spanish",
index: 2
},
{
name: "Kate",
age: 22,
nationality: "English",
index: 3
},
];
If I want to return a new array with only the people with English nationality I'd use filter, like this:
let englishPerson = data.filter(el => el.nationality === 'English');
console.log(englishPerson);
And this will log the following:
> Array [Object { name: "David", age: 25, nationality: "English", index: 1 }, Object { name: "Kate", age: 22, nationality: "English", index: 3 }]
But I would like to reset the index after the data is filtered, so the first object in the new filtered array should have an index of 0, second an index of 1 and so on. In this case David has an index of 1, because it kept the same index from the original data.
You could filter followed by map, but it would be better to do it in one go with reduce - if the item passes the test, add it to the accumulator, with the index of the accumulator's current length:
const data=[{name:"Peter",age:20,nationality:"American",index:0},{name:"David",age:25,nationality:"English",index:1},{name:"Gabriel",age:23,nationality:"Spanish",index:2},{name:"Kate",age:22,nationality:"English",index:3},]
console.log(
data.reduce((a, item) => {
if (item.nationality === 'English') {
a.push({
...item,
index: a.length
});
}
return a;
}, [])
);
You can use Array.prototype.map() to modify the index property of the filtered result:
const data = [
{
name: "Peter",
age: 20,
nationality: "American",
index: 0
},
{
name: "David",
age: 25,
nationality: "English",
index: 1
},
{
name: "Gabriel",
age: 23,
nationality: "Spanish",
index: 2
},
{
name: "Kate",
age: 22,
nationality: "English",
index: 3
},
];
let i=0;
let englishPerson = data.filter(el => el.nationality === 'English').map(el => {
el.index = i; i++;
return el;
});
console.log(englishPerson);
Updated answer based on your comments:
const data = [
{
name: "Peter",
age: 20,
nationality: "American",
index: 0
},
{
name: "David",
age: 25,
nationality: "English",
index: 1
},
{
name: "Gabriel",
age: 23,
nationality: "Spanish",
index: 2
},
{
name: "Kate",
age: 22,
nationality: "English",
index: 3
},
];
let i=0;
let englishPerson = data.filter(el => el.nationality === 'English').map(el => {
if(el.hasOwnProperty('index')){
el.index = i; i++;
}
return el;
});
console.log(englishPerson);
If you want use your solution, with the slightest change, you can try this:
var c=0;
var englishPerson=data.filter(function(el){
return el.nationality=="English" && (el.index=c++)>-1;
});
console.log(englishPerson);
Do this:
const data = [
{
name: "Peter",
age: 20,
nationality: "American",
index: 0
},
{
name: "David",
age: 25,
nationality: "English",
index: 1
},
{
name: "Gabriel",
age: 23,
nationality: "Spanish",
index: 2
},
{
name: "Kate",
age: 22,
nationality: "English",
index: 3
},
];
data.filter(el => Object.values(el).includes('English')).forEach((obj, i) => {obj.index = i; console.log(obj)})
If you want to go with map, then just replace forEachwith map!
You can use from filters.tags.data.map(f => f.Key).toString() replace filter.
Where you use from the map, that index been reset.
For example:
$scope.ret = function(){
data: url,
method: post,
retuen filters.tags.data.map(f => f.Key).toString();
}

Formatting response in Javascript

I have a set of data where i need to format and render in HTML.
This is the data :
var data = [{
name: 'john',
age: 20,
department: 'financial',
group: 'groupA'
},
{
name: 'john',
age: 20,
department: 'healthcare',
group: 'groupA'
},
{
name: 'john',
age: 20,
department: 'insurance',
group: 'groupA'
},
{
name: 'john',
age: 20,
department: 'Realestate',
group: 'groupB'
}, {
name: 'Mark',
age: 20,
department: 'financial',
group: 'groupA'
},
{
name: 'Mark',
age: 21,
department: 'insurance',
group: 'groupA'
},
{
name: 'Mark',
age: 21,
department: 'financial',
group: 'groupB'
}
];
Here i have multiple users where he belongs to different groups and department.I want to format in such a way the if he belongs to same group then get the department which he belongs to in array and for other department show that as a new object.
The response should look like this:
var data_formatted = [
[{
name: 'john',
age: 20,
department: ['financial', 'healthcare', 'insurance'],
group: 'groupA'
},
{
name: 'john',
age: 20,
department: 'Realestate',
group: 'groupB'
}
],
[{
name: 'Mark',
age: 20,
department: ['financial', 'insurance'],
group: 'groupA'
},
{
name: 'Mark',
age: 21,
department: 'financial',
group: 'groupB'
}
]
];
Any suggestions Please!
I think this may help you.
var data = [{
name: 'john',
age: 20,
department: 'financial',
group: 'groupA'
},
{
name: 'john',
age: 20,
department: 'healthcare',
group: 'groupA'
},
{
name: 'john',
age: 20,
department: 'insurance',
group: 'groupA'
},
{
name: 'john',
age: 20,
department: 'Realestate',
group: 'groupB'
}, {
name: 'Mark',
age: 20,
department: 'financial',
group: 'groupA'
},
{
name: 'Mark',
age: 21,
department: 'insurance',
group: 'groupA'
},
{
name: 'Mark',
age: 21,
department: 'financial',
group: 'groupB'
}
];
var data_formatted = [];
var byname = _.groupBy(data, function(element){return element.name});
_.forEach(byname, function(element){
var bygroup = _.groupBy(element, function(element){return element.group});
_.forEach(bygroup, function(element, key, groups){
var departments = _.map(element, 'department');
element[0]['department'] = departments;
groups[key] = element[0];
})
data_formatted.push(_.values(bygroup));
})
console.log(data_formatted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Categories