使用Ramba、下划线或纯Javascript构建关联数组的最佳方法?

使用Ramba、下划线或纯Javascript构建关联数组的最佳方法?,javascript,underscore.js,ramda.js,Javascript,Underscore.js,Ramda.js,最近,我发现自己越来越多地在应用程序中使用关联数组(或hastables)(优点是查找速度快、重复数据消除等) 下面是从我的应用程序中提取的典型代码- var parent1 = { id: 5, name: 'parent 1'}, parent2 = { id: 10, name: 'parent 2'}; var children = [{id: 1, parent: parent1}, {id: 2, parent: parent1}, {id: 3, parent: parent

最近,我发现自己越来越多地在应用程序中使用关联数组(或hastables)(优点是查找速度快、重复数据消除等)

下面是从我的应用程序中提取的典型代码-

 var parent1 = { id: 5, name: 'parent 1'}, parent2  = { id: 10, name: 'parent 2'};
 var children = [{id: 1, parent: parent1}, {id: 2, parent: parent1}, {id: 3, parent: parent1}, {id: 4, parent: parent2}]

var addToHash = function (hashObj, child) {
    var parent = child.parent;
    hashObj[parent.id] = parent;
    return hashObj;
};

var uniqueParents = R.reduce(addToHash, {}, children);
目前我使用Ramda reduce函数

问题-有没有更好的(更简洁的)方法可以用另一个第三方库Ramda或简单的普通Javascript来实现这一点?

reduce
(Ramda或Javascript自己的)在这里并没有给您带来任何好处,它只是增加了编写bug的机会(忘记返回
hashObj
)我会主观地说语义是错误的
reduce
用于累加器更改时,如对数组中的值求和的经典示例中所示

您可以为自己提供一个更适合手头工作的可重用功能,使其更简洁:

function buildHash(hash, array, callback, thisArg) {
    array.forEach(function(entry) {
        callback.call(thisArg, hash, entry);
    });
    return hash;
}
然后:

或者作为
Array.prototype
扩展添加到
Object.defineProperty
中,这样in循环就不会出现意外的

Object.defineProperty(Array.prototype, "buildHash", {
    value: function buildHash(hash, array, callback, thisArg) {
        array.forEach(function(entry) {
            callback.call(thisArg, hash, entry);
        });
        return hash;
    }
});
然后是相同的
addToHash
,但调用更简洁:

var uniqueParents = children.buildHash({}, addToHash);

如果您使用ES2015的箭头功能,所有这些都会变得更简单。:-)

reduce
(Ramda的或JavaScript自己的)在这里并没有给您带来任何好处,它只是增加了一个编写bug的机会(忘记返回
hashObj
),我主观上认为语义是错误的
reduce
用于累加器更改时,如对数组中的值求和的经典示例中所示

您可以为自己提供一个更适合手头工作的可重用功能,使其更简洁:

function buildHash(hash, array, callback, thisArg) {
    array.forEach(function(entry) {
        callback.call(thisArg, hash, entry);
    });
    return hash;
}
然后:

或者作为
Array.prototype
扩展添加到
Object.defineProperty
中,这样in
循环就不会出现意外的

Object.defineProperty(Array.prototype, "buildHash", {
    value: function buildHash(hash, array, callback, thisArg) {
        array.forEach(function(entry) {
            callback.call(thisArg, hash, entry);
        });
        return hash;
    }
});
然后是相同的
addToHash
,但调用更简洁:

var uniqueParents = children.buildHash({}, addToHash);

如果您使用ES2015的箭头功能,所有这些都会变得更简单。:-)

一种可能性:

R.pipe(
  R.map(prop('parent')),                //=> [parent1, parent1, parent1, parent2]
  R.uniq,                               //=> [parent1, parent2]
  R.map(parent => [parent.id, parent]), //=> [[5, parent1], [10, parent1]]
  R.fromPairs                           //=> {5: parent1, 10: parent2}
)(children); 
//=> {5: {id: 5, name: 'parent 1', 10: {id: 10, name: 'parent 2'}}}
请注意,如果您只需要uniq父级列表而不是hashmap,则可以在管道中的第二个函数之后停止

另一个选项与您的类似,它只是将您的函数转换为返回新累加器而不是对其进行变异的函数:

var parentMap = R.reduce((acc, child) => R.assoc(child.parent.id, child.parent, acc), {});
parentMap(children); //=> {5: {id: 5, name: 'parent 1', 10: {id: 10, name: 'parent 2'}}}
一种可能性:

R.pipe(
  R.map(prop('parent')),                //=> [parent1, parent1, parent1, parent2]
  R.uniq,                               //=> [parent1, parent2]
  R.map(parent => [parent.id, parent]), //=> [[5, parent1], [10, parent1]]
  R.fromPairs                           //=> {5: parent1, 10: parent2}
)(children); 
//=> {5: {id: 5, name: 'parent 1', 10: {id: 10, name: 'parent 2'}}}
请注意,如果您只需要uniq父级列表而不是hashmap,则可以在管道中的第二个函数之后停止

另一个选项与您的类似,它只是将您的函数转换为返回新累加器而不是对其进行变异的函数:

var parentMap = R.reduce((acc, child) => R.assoc(child.parent.id, child.parent, acc), {});
parentMap(children); //=> {5: {id: 5, name: 'parent 1', 10: {id: 10, name: 'parent 2'}}}

输入/输出是什么?是否需要单独定义函数?例如,你在重复使用它?你能找出共性并包装
reduce
?(尽管坦率地说,
reduce
在这里并没有为您做任何事情。)这看起来像是一个简单的
for
就可以了(如果您想感觉“更实用”,可以做
forEach
)R.reduce创建实际的关联数组,我稍后在我的应用程序中使用。输入/输出是什么?您需要单独定义函数吗?例如,你在重复使用它?你能找出共性并包装
reduce
?(尽管坦率地说,
reduce
在这里并没有为您做任何事情。)这看起来像是一个简单的
for
就可以了(如果您想感觉“更实用”,可以使用
forEach
)R.reduce创建实际的关联数组,我稍后在我的应用程序中使用。谢谢,回答得很好。我想我会将Object.defineProperty片段集成到我的应用程序中。@JoeKing:只要你不必支持IE8(或兼容模式下的IE9-11)。:-)感谢您的提示,尽管我们只支持IE10+,但我从未考虑过一些客户可能在兼容模式下运行:(谢谢,回答得很好。我想我会将Object.defineProperty片段集成到我的应用程序中。@JoeKing:只要您不必支持IE8(或兼容模式下的IE9-11)。:-)谢谢您的提示,尽管我们只支持IE10+但我从未考虑过某些客户可能在兼容模式下运行:(