使用Ramba、下划线或纯Javascript构建关联数组的最佳方法?
最近,我发现自己越来越多地在应用程序中使用关联数组(或hastables)(优点是查找速度快、重复数据消除等) 下面是从我的应用程序中提取的典型代码-使用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
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+但我从未考虑过某些客户可能在兼容模式下运行:(