使用reduce查询数组中的对象数据并重新格式化

时间:2016-06-22 21:22:56

标签: javascript reduce

我的数据结构如下所示:

var deliveries = [{
    location: "Chicago",
    units: 10
}, {
    location: "San Francisco",
    units: 5
}, {
    location: "Miami",
    units: 2
}, {
    location: "San Francisco",
    units: 13
}, {
    location: "San Francisco",
    units: 2
}, {
    location: "Chicago",
    units: 16
}, {
    location: "Miami",
    units: 1
}];

我希望能够查询任何城市并获得它们在数据结构中出现的次数以及该城市的单位总数。

我必须执行的代码如下:

function getData(arr, city) {
    var numberOfdeliveries = 0;
    var totalUnitsDelivered = 0;


    arr.forEach(function(val, index, arr) {
        if (val.location === city) {
            numberOfdeliveries += 1;
            totalUnitsDelivered += val.units

        }
    })
    return "number of deliveries: " + numberOfdeliveries + ". Total units:" + totalUnitsDelivered
}

getData(deliveries, "San Francisco"); // number of deliveries: 3. Total units:20

这很好用。

但是,我很好奇是否可以使用reduce来返回包含所有城市号码及其所有总单位的数组。

换句话说,最终结果应如下所示:

[{
    "Chicago": 2,
    units: 26
}, {
    "San Francisco":20,
    units: 5
}, {
    "Miami": 2,
    units: 3
}];

我能够得到的最远的是返回一个城市出现次数的物体。

var deliveries = [{
    location: "Chicago",
    units: 10
}, {
    location: "San Francisco",
    units: 5
}, {
    location: "Miami",
    units: 2
}, {
    location: "San Francisco",
    units: 13
}, {
    location: "San Francisco",
    units: 2
}, {
    location: "Chicago",
    units: 16
}, {
    location: "Miami",
    units: 1
}];



var answer = deliveries.reduce(function(obj, val, index, all) {
    if (!obj[val.location]) {
        obj[val.location] = 1
    } else {
        obj[val.location]++
    }

    return obj

}, {})



console.log(answer);  //{ Chicago: 2, 'San Francisco': 3, Miami: 2 }

4 个答案:

答案 0 :(得分:2)

您可以使用结果数组和哈希表来引用结果数组中的元素。



var deliveries = [{ location: "Chicago", units: 10 }, { location: "San Francisco", units: 5 }, { location: "Miami", units: 2 }, { location: "San Francisco", units: 13 }, { location: "San Francisco", units: 2 }, { location: "Chicago", units: 16 }, { location: "Miami", units: 1 }],
    groups = deliveries.reduce(function (hash) {
        return function (r, a) {
            if (!hash[a.location]) {
                hash[a.location] = {};
                hash[a.location][a.location] = 0;
                hash[a.location].units = 0;
                r.push(hash[a.location]);
            }
            hash[a.location][a.location]++;
            hash[a.location].units += a.units;
            return r;
        };
    }(Object.create(null)), []);

console.log(groups);




答案 1 :(得分:1)

如果您计划多次使用此查询,则使用城市作为键将数据映射到hashmap对象会更实用

var cities ={};
deliveries.foreach(function(item){
   var cityObj = cities[item.location] ?  cities[item.location] :{units:0, count:0}

   cityObj.units += item.units;
   cityObj.count ++;

});

会产生类似的东西:

{ "Chicago" :{units: 10, count:2},
  "San Francisco":{units: 5, count:1}
} 

然后当你需要值时:

var city="Chicago",
    units = cities[city].units;

答案 2 :(得分:0)

技术上 Nina 回答了这个问题,但 charlietfl 使用哈希地图的想法我认为更好(即使他/她的代码似乎不起作用) 。所以我想出了如何使用reduce创建哈希映射。我把答案给了Nina只是因为它是"正确的"但这就是我想出来的。

var deliveries = [{
    location: "Chicago",
    units: 10
}, {
    location: "San Francisco",
    units: 5
}, {
    location: "Miami",
    units: 2
}, {
    location: "San Francisco",
    units: 13
}, {
    location: "San Francisco",
    units: 2
}, {
    location: "Chicago",
    units: 16
}, {
    location: "Miami",
    units: 1
}];

var answer = deliveries.reduce(function(obj, val, index, all) {
    if (!obj[val.location]) {
        obj[val.location] = {
            times: 1,
            units: val.units
        }
    } else {

        obj[val.location].times += 1;
        obj[val.location].units += val.units;
    }



    return obj

}, {});

console.log(answer);

答案 3 :(得分:0)

您可以使用地图对象进行分组。

var deliveries = [{ location: "Chicago", units: 10 }, { location: "San Francisco", units: 5 }, { location: "Miami", units: 2 }, { location: "San Francisco", units: 13 }, { location: "San Francisco", units: 2 }, { location: "Chicago", units: 16 }, { location: "Miami", units: 1 }, ];

var result = [];
deliveries.reduce(
	(cities, delivery) => cities.set(delivery.location, [...(cities.get(delivery.location) || []), delivery]), new Map
).forEach((deliveries, city) => {
	var r = {};
	r[city] = deliveries.length;
	r.units = deliveries.reduce((s, c) => s + c.units, 0);
	result.push(r);
})
console.log(result);