Reputation: 1369
I have an array of objects like the following:
[{
animal: "cat",
dateString: "2017-01-03"
},{
animal: "dog",
dateString: "2017-02-05"
},{
animal: "cat",
dateString: "2017-03-04"
}]
and I'd like to create a new array that looks like:
[{
animal: "cat",
values: [
"2017-01-03",
"2017-03-04"
]
},{
animal: "dog",
values: [
"2017-02-05"
]
}]
How can I consolidate the individual object properties into an array of values?
Upvotes: 0
Views: 118
Reputation: 53525
We can simply iterate the array and build a result by mapping each animal to and object that contains its properties, e.g. {'cat': {'animal': 'cat', 'values': ["2017-01-03"]}}
. When we're done, we'll extract only the values:
const arr = [{
animal: "cat",
dateString: "2017-01-03"
},{
animal: "dog",
dateString: "2017-02-05"
},{
animal: "cat",
dateString: "2017-03-04"
}]
let res= {}
arr.forEach(obj => {
if (res[obj.animal]) {
res[obj.animal].values.push(obj.dateString)
} else {
res[obj.animal] = {animal: obj.animal, values: [obj.dateString]}
}
})
res = Object.values(res)
console.log(res)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 14434
Here you first create a new, empty array and a for-loop
. From there you either create a brand new object with of the animal type or just push the dateString
value of the other if it does:
const animals = [{
animal: "cat",
dateString: "2017-01-03"
}, {
animal: "dog",
dateString: "2017-02-05"
}, {
animal: "cat",
dateString: "2017-03-04"
}];
const combined = [];
for (let i = 0; i < animals.length; i++) {
const { animal, dateString } = animals[i];
const animalIndex = combined.findIndex(obj => {
return obj['animal'] === animal;
});
if (animalIndex === -1) {
combined.push({ animal, values: [dateString] });
} else {
combined[animalIndex]['values'].push(dateString);
}
}
console.log(combined);
Upvotes: 0
Reputation: 1946
Since you have not tagged only JS, try this (Vanilla JS)
var x = [{
animal: "cat",
dateString: "2017-01-03"
},{
animal: "dog",
dateString: "2017-02-05"
},{
animal: "cat",
dateString: "2017-03-04"
}];
let usedKeys = [];
let finalArray = [];
for(var z = 0; z < x.length ; z++)
{
if(usedKeys.indexOf(x[z]['animal']) == '-1')
{
usedKeys.push(x[z]['animal']);
finalArray.push({'animal':x[z]['animal'] , 'values':[x[z]['dateString']]});
}
else
{
let targetIndex = usedKeys.indexOf(x[z]['animal']);
finalArray[targetIndex]['values'].push(x[z]['dateString']);
}
}
console.log(finalArray);
Upvotes: 0
Reputation: 22524
You can use array#reduce
to store your object in a new object where values will be grouped on based on animal name. Then, use Object.values
to get the result.
var data = [{ animal: "cat", dateString: "2017-01-03" },{ animal: "dog", dateString: "2017-02-05" },{ animal: "cat", dateString: "2017-03-04" }];
var result = data.reduce((o, {animal, dateString}) => {
o[animal] ? o[animal].values.push(dateString) : o[animal] = {animal, values: [dateString]}
return o;
},{});
var output = Object.values(result);
console.log(output);
Upvotes: 0
Reputation: 4185
You could use forEach method to double sort your array.
var arr = [{
animal: "cat",
dateString: "2017-01-03"
},{
animal: "dog",
dateString: "2017-02-05"
},{
animal: "cat",
dateString: "2017-03-04"
}];
var sorted = [];
arr.forEach(function callback(arrVal, index1, array1) {
sorted.forEach(function callback(sortVal, index2, array2) {
if (arrVal == sortVal) {
sorted[index2].values.push(arrVal.dateString);
} else {
sorted.push({animal: arr[index1].animal, values: [arr[index1].dateString]});
}
});
});
Hope it will help.
Upvotes: 0
Reputation: 3687
var data=[{
animal: "cat",
dateString: "2017-01-03"
},{
animal: "dog",
dateString: "2017-02-05"
},{
animal: "cat",
dateString: "2017-03-04"
}]
var ans = data.reduce(function(accumulator, element) {
var elementInAccumulator = accumulator[element.animal]
if(elementInAccumulator) {
if(Array.isArray(elementInAccumulator.values)) {
elementInAccumulator.values.push(element.dateString)
}
else {
var arr=[]
arr.push(elementInAccumulator.dateString)
arr.push(element.dateString)
elementInAccumulator.values= arr
delete(elementInAccumulator.dateString)
}
}
else {
accumulator[element.animal] = element
}
return accumulator
}, {})
console.log(Object.keys(ans).map(function(element) {
return ans[element]
}))
Upvotes: 0
Reputation: 763
Without lodash/ramda u can do
const a = [
{
animal: 'cat',
dateString: '2017-01-03'
}, {
animal: 'dog',
dateString: '2017-02-05'
}, {
animal: 'cat',
dateString: '2017-03-04'
}
]
const b = Object.values(a.reduce((a, b) => {
if (a[b.animal]) {
a[b.animal].values.push(b.dateString)
} else {
a[b.animal] = {animal: b.animal, values: [b.dateString]}
}
return a
}, {}))
Upvotes: 2