在阵列上运行两次reduce函数?导致未定义的节点js

时间:2014-10-30 07:22:54

标签: node.js

我遇到节点js的问题。我认为这与代码如何运行异步有关。 是因为reduce函数是异步运行的吗? 如果是这样,为了一个接一个地运行这些功能,我必须遵循什么惯用模式?

我正在尝试两次运行reduce操作,第二次我得到一个未定义的

function hello(){

var values = [
    {"a": 1},
    {"b": 2},
    {"c": 3},
    {"d": 4},
    {"b": 5},
    {"a": 6},
    {"a": 7},
    {"b": 8},
    {"c": 9},
    {"d": 10}
];

var kvList = values.reduce(function (result, element) {

    var key = Object.keys(element);
    var val = element[key];

    // if undefined create an array.
    result[key] = result[key] || [];
    result[key].push(val);

    return result;

}, []);

console.log(kvList);
console.log(kvList[0]); // becomes undefined here.
var pairs = kvList.reduce(function (result, element) {

    console.log("HELLO");
    var key = Object.keys(element)[0];

    console.log(element);

    var subArray = element[key];

    var total = subArray.reduce(function (result, element) {
        return result + element;
    }, 0);

    result[key] = total;
    return result;

}, []);

console.log(pairs);

};

您好();

1 个答案:

答案 0 :(得分:0)

Array.prototype.reduce()不会异步运行。

问题是.reduce()对数组元素(顺序编号的元素,通过从0开始的数字索引访问)进行操作。你的第一个数组有数组元素。然而,您的第一个.reduce()的结果是一个数组对象,但只有'a','b','c'等属性,并且没有实际的数组元素。例如,在您进行第一次.reduce()操作后kvList.length === 0,因此第二个.reduce()不会像您希望的那样循环遍历元素。

第一个.reduce()循环中的罪魁祸首是这些代码行:

// if undefined create an array.
result[key] = result[key] || [];
result[key].push(val);

这会向result添加属性名为key的属性。它实际上并没有向数组添加元素,因此第二个.reduce()没有要操作的数组元素。


好的,既然你已经显示了想要的结果,那么就会产生这样的结果:

var values = [
    {"a": 1}, {"b": 2}, {"c": 3}, {"d": 4}, {"b": 5},
    {"a": 6}, {"a": 7}, {"b": 8}, {"c": 9}, {"d": 10}
];

var dict = {};
values.forEach(function(obj) {
    // iterate the properties of each object in the array
    for (var prop in obj) {
        // if not already in the dict, add an empty array to the dict for this property name
        if (!(prop in dict)) {
            dict[prop] = [];
        }
        // add this number to the array for this dict entry
        dict[prop].push(obj[prop]);
    }
});

// dict is {"a":[1,6,7],"b":[2,5,8],"c":[3,9],"d":[4,10]}

// process back into an array
var result = [];
// iterate each property in the dict
for (var prop in dict) {
    // create an object that is of this form {prop: [val1, val2, val3]}
    // and put it in the result array
    var temp = {};
    temp[prop] = dict[prop];
    result.push(temp);
}

// result is [{"a":[1,6,7]},{"b":[2,5,8]},{"c":[3,9]},{"d":[4,10]}]

工作演示:http://jsfiddle.net/jfriend00/q8u208y4/

仅供参考,您使用单个密钥的对象的数据结构有点奇怪且难以使用。我想知道为什么最终结果不是dict中的内容,这实际上更容易在代码中使用,因为您可以直接迭代属性以获取每个属性和相应的数组。