Related
I have the data from the database and I want to push the duplicate value to each array. I attach the exact example I want.
// origin data
const data = [
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Tommy",
age: 20,
},
{
name: "Tommy",
age: 20,
},
];
//result that I want to get
arr1 = [
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
];
arr2 = [
{
name: "Tommy",
age: 20,
},
{
name: "Tommy",
age: 20,
},
];
I want to create an array based on the name in this data and push it. Can anyone help?
One way would be to use reduce together with Object.values:
const data = [
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Tommy",
age: 20,
},
{
name: "Tommy",
age: 20,
}
];
const result = Object.values(data.reduce((acc, cur) => {
const key = `${cur.name}:${cur.age}`;
const prev = acc[key] || [];
return {
...acc,
[key]: prev.concat(cur)
}
}, {}));
console.log(result);
Having the following input array:
const initialArray = [{name: 'john', age: 12, height: 178, likes: 'music'},
{name: 'mike', age: 22, height: 181, likes: 'sport'},
{name: 'anna', age: 18, height: 175, likes: 'sleep'},
{name: 'paul', age: 24, height: 170, likes: 'drink'}
];
I want to build a new array of objects that contains only some properties, for example, just name and height. The result would be:
result = [{name: 'john', height: 178},
{name: 'mike', height: 181},
{name: 'anna', height: 175},
{name: 'paul', height: 170}
];
Tried with map but probably something is wrong:
const result = initialArray.map((a) => {
a.name, a.height
});
You should either use return keyword inside {} or warp the code with () (parenthesis).
You can try using Destructuring assignment which allow you to specify the property names you want in the resulting objects:
const initialArray = [
{name: 'john', age: 12, height: 178, likes: 'music'},
{name: 'mike', age: 22, height: 181, likes: 'sport'},
{name: 'anna', age: 18, height: 175, likes: 'sleep'},
{name: 'paul', age: 24, height: 170, likes: 'drink'}
];
const result = initialArray.map(({name, height}) => ({name,height}));
console.log(result);
you should return the object like below.
const result = initialArray.map((a) => {
return {name:a.name, height:a.height}
});
You can easily achieve this using map, reduce or for..of loop
1) Using map
const initialArray = [
{ name: "john", age: 12, height: 178, likes: "music" },
{ name: "mike", age: 22, height: 181, likes: "sport" },
{ name: "anna", age: 18, height: 175, likes: "sleep" },
{ name: "paul", age: 24, height: 170, likes: "drink" },
];
const result = initialArray.map(({ name, height }) => ({ name, height }));
console.log(result);
2) Using reduce
const initialArray = [
{ name: "john", age: 12, height: 178, likes: "music" },
{ name: "mike", age: 22, height: 181, likes: "sport" },
{ name: "anna", age: 18, height: 175, likes: "sleep" },
{ name: "paul", age: 24, height: 170, likes: "drink" },
];
const result = initialArray.reduce((acc, { name, height }) => {
acc.push({ name, height });
return acc;
}, []);
console.log(result);
3) Using for..of loop
const initialArray = [
{ name: "john", age: 12, height: 178, likes: "music" },
{ name: "mike", age: 22, height: 181, likes: "sport" },
{ name: "anna", age: 18, height: 175, likes: "sleep" },
{ name: "paul", age: 24, height: 170, likes: "drink" },
];
const result = [];
for (let { name, height } of initialArray) {
result.push({ name, height });
}
console.log(result);
Another way would be with lodash's pick (if you need to dynamically resolve the name of the properties) or ramda's pick methods are doing exactly this
const result = initialArray.map(R.pick(['name', 'height']));
I have for example this dataset:
const order = [
{ key: "job", direction: "ascending" },
{ key: "age", direction: "descending" },
];
const records = [
{ name: "christian", age: 40, job: "developer" },
{ name: "andrew", age: 48, job: "developer" },
{ name: "elisabeth", age: 31, job: "floor manager" },
{ name: "oscar", age: 61, job: "floor manager" },
{ name: "gisela", age: 51, job: "area manager" },
{ name: "buffy", age: 27, job: "trainee" },
{ name: "carl", age: 23, job: "trainee" },
];
I need to sort the records array according to the criteria from order array.
I ended up with this solution:
const sorted = records.sort(
(recordA, recordB) =>
recordA.job.localeCompare(recordB.job) || recordA.age - recordB.age
);
But I cant understand how can I use the order array instead of hardcoded the job and age properties. The order array can have many properties.
You could take a closure over the wanted order and check the value if finite then return the delta or treat the values as string.
Inside sorting function iterate as long as the return value is falsy and take this value as return value for sorting.
const
sortBy = order => (a, b) => {
let r;
order.some(({ key, direction }) => r = (isFinite(a[key]) && isFinite(b[key])
? a[key] - b[key]
: a[key].toString().localeCompare(b[key])
) * (direction === 'ascending' || -1))
return r;
},
records = [{ name: "christian", age: 40, job: "developer" }, { name: "andrew", age: 48, job: "developer" }, { name: "elisabeth", age: 31, job: "floor manager" }, { name: "oscar", age: 61, job: "floor manager" }, { name: "gisela", age: 51, job: "area manager" }, { name: "buffy", age: 27, job: "trainee" }, { name: "carl", age: 23, job: "trainee" }],
order = [{ key: "job", direction: "ascending" }, { key: "age", direction: "descending" }];
console.log(records.sort(sortBy(order)));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Just loop over the order data and make the comparisons:
let order = [{ key: "job", direction: "ascending" }, { key: "age", direction: "descending" }];
let records = [{ name: "christian", age: 40, job: "developer" }, { name: "andrew", age: 48, job: "developer" }, { name: "elisabeth", age: 31, job: "floor manager" }, { name: "oscar", age: 61, job: "floor manager" }, { name: "gisela", age: 51, job: "area manager" }, { name: "buffy", age: 27, job: "trainee" }, { name: "carl", age: 23, job: "trainee" }];
records.sort(function (a, b) {
for (let {key, direction} of order) {
if (a[key] !== b[key]) return (direction[0] === "a") === (a[key] < b[key]) ? -1 : 1;
}
return 0;
});
console.log(records);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use (a[key] > b[key]) - (a[key] < b[key]) to compare two values either lexically or numerically (if both are numbers). This could then be used like:
const order = [
{ key: "job", direction: "ascending" },
{ key: "age", direction: "descending" },
];
const records = [
{ name: "christian", age: 40, job: "developer" },
{ name: "andrew", age: 48, job: "developer" },
{ name: "elisabeth", age: 31, job: "floor manager" },
{ name: "oscar", age: 61, job: "floor manager" },
{ name: "gisela", age: 51, job: "area manager" },
{ name: "buffy", age: 27, job: "trainee" },
{ name: "carl", age: 23, job: "trainee" },
];
const compare = (key) => (a, b) => (a[key] > b[key]) - (a[key] < b[key]);
const or = (a, b) => (...v) => a(...v) || b(...v);
const sorter = order.map(it => compare(it.key)).reduce(or);
const sorted = records.sort(sorter);
console.log(sorted);
The implementation of direction was left to the reader
I have an array of objects as mentioned below,
var arraydata =[
{ id:1, name:"Abraham", age:20,gender:"male"},
{ id:2, name:"Annie", age:25,gender:"female"},
{ id:3, name:"Ryan", age:40,gender:"male"},
{ id:4, name:"Wayne", age:31,gender:"male"},
{ id:5, name:"Paul", age:45,gender:"male"}
];
how to convert this to a JSON data, which has only "id" and "name" field?
syntax is wrong age=20,gender="male" change it to age:20,gender:"male"
var arraydata =[
{ id:1, name:"Abraham", age: 20, gender:"male"},
{ id:2, name:"Annie", age: 25, gender:"female"},
{ id:3, name:"Ryan", age: 28, gender:"male"},
{ id:4, name:"Wayne", age: 19, gender:"male"},
{ id:5, name:"Paul", age: 45,gender:"male"}
];
var ans= arraydata.map(function(a){
return {id:a.id,name:a.name};
})
console.log(ans);
You can use the delete operator which remove a property from an object.
var arraydata = [{
id: 1,
name: "Abraham",
age : 20,
gender : "male"
}, {
id: 2,
name: "Annie",
age : 25,
gender : "female"
}, {
id: 3,
name: "Ryan",
age : 40,
gender : "male"
}, {
id: 4,
name: "Wayne",
age : 31,
gender : "male"
}, {
id: 5,
name: "Paul",
age : 45,
gender : "male"
}];
arraydata.forEach(function(item){ delete item.age; delete item.gender });
console.log(arraydata);
var arraydata =[
{ id:1, name:"Abraham", age: 20, gender: "male"},
{ id:2, name:"Annie", age: 25, gender: "female"},
{ id:3, name:"Ryan", age: 28, gender: "male"},
{ id:4, name:"Wayne", age: 19, gender: "male"},
{ id:5, name:"Paul", age: 45, gender: "male"}
];
var _ = arraydata.map(function(item) {
return { id: item.id, name: item.name };
});
var jsonData = JSON.stringify(_);
console.log(jsonData);
You can of course chain together the two steps.
Fiddle
I am trying to determine the best data-type to sort an array of objects, into groups defined by properties. I have an array of objects, like so:
var people = [
{
name: 'Pete',
gender: 'Male',
age: 22
},
{
name: 'Samantha',
gender: 'Female',
age: 20
},
{
name: 'Frank',
gender: 'Male',
age: 22
},
{
name: 'Gary',
gender: 'Male',
age: 21
},
{
name: 'Maria',
gender: 'Female',
age: 20
},
{
name: 'Hannah',
gender: 'Female',
age: 21
},
{
name: 'Pete',
gender: 'Male',
age: 20
}
];
I need to group these objects into an arbitrary-defined group. E.g.:
Group 1: gender
Group 2: age
(This can be defined by the server and can change to contain a third group if we wish.)
Which then gives me (visually):
Male:
21:
Gary
22:
Pete
Frank
Female
20:
Samantha
Maria
21:
Hannah
I think the appropriate data type would be an object of objects. I.e.:
{
Male: {
21: {
[
{
name: 'Gary',
gender: 'Male',
age: 21
}
]
},
22: {
[
{
name: 'Pete',
gender: 'Male',
age: 22
},
{
name: 'Frank',
gender: 'Male',
age: 22
}
]
}
},
Female: {
20: {
[
{
name: 'Samantha',
gender: 'Female',
age: 20
},
{
name: 'Maria',
gender: 'Female',
age: 20
}
]
},
21: {
[
{
name: 'Hannah',
gender: 'Female',
age: 21
}
]
}
}
}
But I cannot work out, for the life of me, an appropriate algorithm to sort these objects into a data-type which represents the above.
There is a useful utility in underscore.js called _.groupBy(arr, callback) which I can use as follows:
_.groupBy(people, function (person) {
var props = ['gender', 'age'], // server-defined
prop = [];
for (var i = 0, length = props.length; i < length; i++) {
prop.push(person[props[i]]);
}
return prop.join('|');
});
This gives me a 1-depth object which I can use a for...in loop to iterate over the keys, and loop through to build the object above, but it's that bit of the code I'm stuck on.
The returned object would be:
{
"Male|22": [
{
"name": "Pete",
"gender": "Male",
"age": 22
},
{
"name": "Frank",
"gender": "Male",
"age": 22
}
],
"Female|20": [
{
"name": "Samantha",
"gender": "Female",
"age": 20
},
{
"name": "Maria",
"gender": "Female",
"age": 20
}
],
"Male|21": [
{
"name": "Gary",
"gender": "Male",
"age": 21
}
],
"Female|21": [
{
"name": "Hannah",
"gender": "Female",
"age": 21
}
],
"Male|20": [
{
"name": "Pete",
"gender": "Male",
"age": 20
}
]
}
I'm thinking of then looping through each key in the object, splitting at the pipe (|) and using recursion to construct a new object of objects containing the groups/array of data.
That's such a horrendous way of achieving this but I have no idea how to do it otherwise.
Is there a better way I'm missing?
Maybe this helps you. It utilises an array with the properties of the object and the result is grouped by the content of the properties.
The forEach loop iterates over the data. The reduce loop is for generating grouped properties for every given group and if it is the last one it returns an array, if not already there.
The last step is to push the value of one of people to the array.
var people = [{ name: 'Pete', gender: 'Male', age: 22 }, { name: 'Samantha', gender: 'Female', age: 20 }, { name: 'Frank', gender: 'Male', age: 22 }, { name: 'Gary', gender: 'Male', age: 21 }, { name: 'Maria', gender: 'Female', age: 20 }, { name: 'Hannah', gender: 'Female', age: 21 }, { name: 'Pete', gender: 'Male', age: 20 }],
groups = ['gender', 'age'],
grouped = {};
people.forEach(function (a) {
groups.reduce(function (o, g, i) { // take existing object,
o[a[g]] = o[a[g]] || (i + 1 === groups.length ? [] : {}); // or generate new obj, or
return o[a[g]]; // at last, then an array
}, grouped).push(a);
});
document.write('<pre>' + JSON.stringify(grouped, 0, 4) + '</pre>');
you can use lodash
groupBy(people, (item) => item.age + item.gender);
I realy don't understand why people always use frameworks for that kind of things.
Vanilla is faster and this is not too hard to code...
var people = [ { name: 'Pete', gender: 'Male', age: 22 }, { name: 'Samantha', gender: 'Female', age: 20 }, { name: 'Frank', gender: 'Male', age: 22 }, { name: 'Gary', gender: 'Male', age: 21 }, { name: 'Maria', gender: 'Female', age: 20 }, { name: 'Hannah', gender: 'Female', age: 21 }, { name: 'Pete', gender: 'Male', age: 20 }];
var grouped = {}; // final object
for (var i=0,len=people.length,p;i<len;i++) { // faster than .forEach
p = people[i];
if (grouped[p.gender] === undefined) // twice faster then hasOwnProperty
grouped[p.gender] = {};
if (grouped[p.gender][p.age] === undefined)
grouped[p.gender][p.age] = [];
grouped[p.gender][p.age].push(p); // your groupby is HERE xD
}
document.getElementById('grouped').innerHTML = JSON.stringify(grouped, null, 2)
<pre id="grouped"></pre>
I'm going to disagree with you about your expected output. I think you should just have an object with Male and Female array properties and use this code to populate the arrays:
var obj = people.reduce(function (p, c, i) {
p[c.gender].push(c);
return p;
}, { Male: [], Female: [] });
If you want to then filter those arrays you can write functions like this:
function getMaleByAge(obj, age) {
return obj.Male.filter(function (el) {
return el.age === age;
})
}
getMaleByAge(obj, 21); // { name: "Gary", gender: "Male", age: 21 }
DEMO
Using _.groupBy & _.map
var output = _.map(_.groupBy(people, 'gender'),function(obj, key){
var temp = {};
temp[key] = _.groupBy(obj, 'age')
return temp;
});
console.log(JSON.stringify(output, null,' '))
Will give following output
[{
"Male": {
"20": [
{
"name": "Pete",
"gender": "Male",
"age": 20
}
],
"21": [
{
"name": "Gary",
"gender": "Male",
"age": 21
}
],
"22": [
{
"name": "Pete",
"gender": "Male",
"age": 22
},
{
"name": "Frank",
"gender": "Male",
"age": 22
}
]
}
},
{
"Female": {
"20": [
{
"name": "Samantha",
"gender": "Female",
"age": 20
},
{
"name": "Maria",
"gender": "Female",
"age": 20
}
],
"21": [
{
"name": "Hannah",
"gender": "Female",
"age": 21
}
]
}
}
]