将事物分类为类型的良好 JavaScript 模式是什么?
我正在寻找一种方法(在 JavaScript 中)将一组对象收集到多个数组中,其中每个数组包含某种类型的对象,并且数组作为值存储在关联数组中,键是类型。例如:
输入:
[<apple>, <cat>, <pear>, <mercedes>, <dog>, <ford>, <orange>]
输出:
{
'fruit': [<apple>, <pear>, <orange>],
'animal': [<cat>, <dog>],
'car': [<mercedes>, <ford>]
}
在 ruby 中,您可以执行以下操作:
things_by_type = {}
things.each do |thing|
(things_by_type[thing.type] ||= []) << thing
end
这是很好且简洁的。
在 JavaScript 中做同样的事情有什么好的模式,既简洁又高效?我可以做这样的事情,但它不是那么好:
var thing, things_by_type = {};
for (var i = 0; i < things.length; i++) {
thing = things[i];
if(things_by_type[thing.type]) {
things_by_type[thing.type].push(thing);
} else {
things_by_type[thing.type] = [thing];
}
}
I'm looking for a way (in JavaScript) to collect a set of objects into multiple arrays, where each array contains a certain type of object, and the arrays are stored as values in an associative array, with the keys being the types. For example:
Input:
[<apple>, <cat>, <pear>, <mercedes>, <dog>, <ford>, <orange>]
Output:
{
'fruit': [<apple>, <pear>, <orange>],
'animal': [<cat>, <dog>],
'car': [<mercedes>, <ford>]
}
In ruby, you could do the following:
things_by_type = {}
things.each do |thing|
(things_by_type[thing.type] ||= []) << thing
end
which is nice and concise.
What's a good pattern for doing the same thing in JavaScript that's concise and efficient? I could do something like this, but it's not as nice:
var thing, things_by_type = {};
for (var i = 0; i < things.length; i++) {
thing = things[i];
if(things_by_type[thing.type]) {
things_by_type[thing.type].push(thing);
} else {
things_by_type[thing.type] = [thing];
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我不确定这是否是一个好的模式,但它与您的 ruby 示例类似:
如果您可以假设 Javascript 1.6:
I'm not sure if it's a good pattern, but it's similar to your ruby sample:
And if you can assume Javascript 1.6:
事实上,你可以让它变得更好。
首先,
Hash.new
采用一个块参数,每次引用不存在的键时都会调用该参数。您可以使用它来创建该密钥。这样你就可以摆脱块内的条件逻辑。其次,这里的内容称为“折叠”或“减少”:将集合(对象数组)“折叠”或“减少”为单个值(哈希,令人困惑的是,它也恰好是一个集合,但仍然是一个值)。
通常,您可以通过查找初始化某些变量的位置,然后循环遍历集合并在循环的每次迭代中操作该变量,轻松地发现这种模式。
Ruby 通过
Enumerable#reduce
方法内置了折叠功能:但是您真正所做的是按其元素的类型属性对数组进行分组,这也是构建的Ruby 中为
Enumerable#group_by
:可以通过使用
Symbol#to_proc
进一步简化,不幸的是,ECMAScript 没有
groupBy
,也没有默认值不存在的属性的值,但它确实有Array.prototype.reduce
:Actually, you can make that even nicer.
First off,
Hash.new
takes a block argument which will be called every time a non-existing key is referenced. You can use that to create that key. That way you get rid of the conditional logic inside the block.Secondly, what you have here is called a
fold
orreduce
: you are "folding" or "reducing" a collection (the array of objects) into a single value (the hash, which confusingly also happens to be a collection, but is nonetheless a single value).You can generally easily spot this pattern by looking for places where you initialize some variable, then loop over a collection and manipulate that variable at every iteration of the loop.
Ruby has folding built in, via the
Enumerable#reduce
method:But what you are really doing, is grouping the array by the type attribute of its elements, which is also built into Ruby as
Enumerable#group_by
:Which can be further simplified by using
Symbol#to_proc
toUnfortunately, ECMAScript doesn't have
groupBy
, nor default values for non-existing properties, but it does haveArray.prototype.reduce
:几乎相同的代码,但工作方式有点不同,您可以更轻松地使用花哨的 set 函数,它分离了逻辑:
almost the same code, but works a bit different, you can use the fancy set function easier and it separates logic: