I have following array of hashes and want to convert it into an array like the one at the bottom of the post.
var responseData = [
{deviceType: "Smartphone", deviceCount: 14},
{deviceType: "Tablet", deviceCount: 11},
{deviceType: "Notebook", deviceCount: 3},
{deviceType: "Desktop", deviceCount: 2},
{deviceType: "Smartphone", deviceCount: 1},
{deviceType: "Tablet", deviceCount: 10},
{deviceType: "Notebook", deviceCount: 30},
{deviceType: "Desktop", deviceCount: 20}
];
function dataMapper(responseData){
let series = [];
if(responseData && responseData.length){
responseData.forEach(function(resource){
existingElement = series.filter(function (item) {
return item.deviceType === resource.deviceType;
});
if (existingElement) {
deviceCount = existingElement[0].deviceCount + resource.deviceCount;
existingElement[0].deviceCount = deviceCount
}else{
series[0].push({deviceType: resource.deviceType, y: resource.deviceCount});
}
});
}
return series
}
console.log(dataMapper(responseData))
I have following array of hashes and want to convert it into an array like the one at the bottom of the post.
var responseData = [
{deviceType: "Smartphone", deviceCount: 14},
{deviceType: "Tablet", deviceCount: 11},
{deviceType: "Notebook", deviceCount: 3},
{deviceType: "Desktop", deviceCount: 2},
{deviceType: "Smartphone", deviceCount: 1},
{deviceType: "Tablet", deviceCount: 10},
{deviceType: "Notebook", deviceCount: 30},
{deviceType: "Desktop", deviceCount: 20}
];
function dataMapper(responseData){
let series = [];
if(responseData && responseData.length){
responseData.forEach(function(resource){
existingElement = series.filter(function (item) {
return item.deviceType === resource.deviceType;
});
if (existingElement) {
deviceCount = existingElement[0].deviceCount + resource.deviceCount;
existingElement[0].deviceCount = deviceCount
}else{
series[0].push({deviceType: resource.deviceType, y: resource.deviceCount});
}
});
}
return series
}
console.log(dataMapper(responseData))
I want to convert this into:
var expectedResult = [
{deviceType: "Smartphone", deviceCount: 15},
{deviceType: "Tablet", deviceCount: 21},
{deviceType: "Notebook", deviceCount: 33},
{deviceType: "Desktop", deviceCount: 22}
];
Share
Improve this question
edited Feb 19, 2018 at 13:55
Heretic Monkey
12.1k7 gold badges61 silver badges131 bronze badges
asked Feb 19, 2018 at 13:07
Gol. D RogerGol. D Roger
1191 silver badge8 bronze badges
2
- your filter method is not working correctly – messerbill Commented Feb 19, 2018 at 13:12
- Possible duplicate of Sum javascript object propertyA values with same object propertyB in array of objects – Heretic Monkey Commented Feb 19, 2018 at 13:55
8 Answers
Reset to default 5Using an ES6 Map and reduce
:
const responseData = [{deviceType: "Smartphone", deviceCount: 14},{deviceType: "Tablet", deviceCount: 11},{deviceType: "Notebook", deviceCount: 3},{deviceType: "Desktop", deviceCount: 2},{deviceType: "Smartphone", deviceCount: 1},{deviceType: "Tablet", deviceCount: 10},{deviceType: "Notebook", deviceCount: 30},{deviceType: "Desktop", deviceCount: 20}];
const result = Array.from(
responseData.reduce(
(acc, o) => (acc.get(o.deviceType).deviceCount += o.deviceCount, acc),
new Map(responseData.map( ({deviceType}) => [deviceType, {deviceType, deviceCount: 0} ] ))
).values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Its much easier if you use a hashtable and build up the result in parallel:
const hash = {}, result = [];
for(const {deviceType, deviceCount} of responseData){
if(hash[deviceType]){
hash[deviceType].deviceCount += deviceCount;
} else {
result.push(hash[deviceType] = {deviceType, deviceCount});
}
}
If you really want to iterate over the array, you should use find
instead of filter
:
const result = [];
for(const {deviceType, deviceCount} of responseData){
const exists = result.find(device => device.deviceType === deviceType);
if(exists){
exists.deviceCount += deviceCount;
} else {
result.push({deviceType, deviceCount });
}
}
You could take a hash table as reference to the counting object and return the array with the objects.
var responseData = [{ deviceType: "Smartphone", deviceCount: 14 }, { deviceType: "Tablet", deviceCount: 11 }, { deviceType: "Notebook", deviceCount: 3 }, { deviceType: "Desktop", deviceCount: 2 }, { deviceType: "Smartphone", deviceCount: 1 }, { deviceType: "Tablet", deviceCount: 10 }, { deviceType: "Notebook", deviceCount: 30 }, { deviceType: "Desktop", deviceCount: 20 }],
hash = Object.create(null),
result = responseData.reduce(function (r, o) {
if (!hash[o.deviceType]) {
hash[o.deviceType] = { deviceType: o.deviceType, deviceCount: 0 };
r.push(hash[o.deviceType]);
}
hash[o.deviceType].deviceCount += o.deviceCount;
return r;
}, []);
console.log(result);
Another solution could be to use a Map
and get later an array of all counted devices.
var responseData = [{ deviceType: "Smartphone", deviceCount: 14 }, { deviceType: "Tablet", deviceCount: 11 }, { deviceType: "Notebook", deviceCount: 3 }, { deviceType: "Desktop", deviceCount: 2 }, { deviceType: "Smartphone", deviceCount: 1 }, { deviceType: "Tablet", deviceCount: 10 }, { deviceType: "Notebook", deviceCount: 30 }, { deviceType: "Desktop", deviceCount: 20 }],
result = Array.from(
responseData.reduce((map, { deviceType, deviceCount }) => map.set(deviceType, (map.get(deviceType) || 0) + deviceCount), new Map),
([ deviceType, deviceCount ]) => ({ deviceType, deviceCount })
);
console.log(result);
One of the way where we bring your expected result is by doing like this:
var responseData = [{
deviceType: "Smartphone",
deviceCount: 14
},
{
deviceType: "Tablet",
deviceCount: 11
},
{
deviceType: "Notebook",
deviceCount: 3
},
{
deviceType: "Desktop",
deviceCount: 2
},
{
deviceType: "Smartphone",
deviceCount: 1
},
{
deviceType: "Tablet",
deviceCount: 10
},
{
deviceType: "Notebook",
deviceCount: 30
},
{
deviceType: "Desktop",
deviceCount: 20
}
];
var pushedType = [];
var summedData = [];
for (var i in responseData) {
if (pushedType.indexOf(responseData[i].deviceType) === -1) {
summedData.push(responseData[i]);
pushedType.push(responseData[i].deviceType);
} else {
summedData[pushedType.indexOf(responseData[i].deviceType)].deviceCount += responseData[i].deviceCount;
}
}
$(".result").html(JSON.stringify(summedData))
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="result"></div>
Hope it helps you :)
I added this fiddle for you: https://jsfiddle/6zuux7jq/6/
var responseData = [
{deviceType: "Smartphone", deviceCount: 14},
{deviceType: "Tablet", deviceCount: 11},
{deviceType: "Notebook", deviceCount: 3},
{deviceType: "Desktop", deviceCount: 2},
{deviceType: "Smartphone", deviceCount: 1},
{deviceType: "Tablet", deviceCount: 10},
{deviceType: "Notebook", deviceCount: 30},
{deviceType: "Desktop", deviceCount: 20}
];
function dataMapper(responseData){
var series = {};
if(responseData && responseData.length){
responseData.forEach(function(element){
series[element.deviceType] = Number.isInteger(series[element.deviceType]) ? series[element.deviceType] + element.deviceCount : element.deviceCount
});
}
var tmp = []
for (var i in series) {
tmp.push({deviceType: i, deviceCount: series[i]})
}
return tmp
}
console.log(dataMapper(responseData))
Greetings
I suggest to use lodash
let result = _.groupBy(responseData , 'deviceType');
result = Object.keys(result).map(key => {
return {
deviceType: key,
deviceCount: _.sumBy(result[key], 'deviceCount')} ;
});
or with Array.reduce()
:
let transformObj = {};
responseData.reduce((prev,cur) =>{
const key = cur.deviceType;
if(!prev[key]){
prev[key] = 0;
}
prev[key] += cur.deviceCount;
return prev;
},transformObj);
const results = Object.keys(transformObj).map(key => {
return {
deviceType: key,
deviceCount: transformObj[key]
}
});
Here is my solution:
responseData.forEach(function(item) {
if (expectedResult[item.deviceType] == null) {
expectedResult[item.deviceType] = item;
} else {
expectedResult[item.deviceType].deviceCount += item.deviceCount;
}
});
Try this
const results = []
var temp = {};
responseData.map(function(item){
temp[item.deviceType] = (temp[item.deviceType] || 0) + item.deviceCount;;
})
Object.keys(temp).forEach(function(key) {
results.push({ deviceType: key, deviceCount: temp[key]});
})
console.log(results);
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744847454a4596927.html
评论列表(0条)