2012-06-18 70 views
3

我试图尽可能高效地使用CoffeeScript理解。我想我有一个基本的映射 - 将一个列表变成另一个 - 但搜索对我来说似乎仍然很冗长。CoffeeScript中的列表/对象搜索

说我有地图项目的商店:

shopMap: 
    toyStore: ["games", "puzzles"] 
    bookStore: ["novels", "picture books"] 

,并给出一个项目,我想找出哪些店是在什么做,在CoffeeScript中的最佳方式是什么?

这里是我怎么能在JavaScript做:

var shop = findShop(item); 

function findShop(item) { 
    for (shop in shopMap) 
     itemList = shopMap[shop] 
     for (i = 0, ii = itemList.length; i<ii; i++) { 
     if (itemList[i] === item) { 
      return shop; 
     } 
     } 
    } 
} 

我使用的功能,使其能够迅速摆脱与return语句的循环,而是采用中断,但功能是怎么样的fugly,因为这只用了一次。

那么有一个更短的CS等价物,最好不需要创建一个新的功能?

回答

7

您可以尝试this

findShop = (item) -> 
    for shop, items of shopMap 
    return shop if item in items 

如果你真的想尝试用一个列表理解,这相当于:

findShop = (item) -> 
    (shop for shop, items of shopMap when item in items)[0] 

但我认为第一个读更好的(也没有按不需要为结果生成中间数组)。这将是一个更好的办法国际海事组织如果你想find all shops某个商品:

findShops = (item) -> 
    shop for shop, items of shopMap when item in items 
+0

这很好,谢谢。 –

1

如果这是一个常见的操作,你可能会更好前面创建中间数据结构,并直接做查找。

shopMap = 
    toyStore: ["games", "puzzles"] 
    bookStore: ["novels", "picture books"] 

categoryMap = {} 
for k, v of shopMap 
    for category in v 
    categoryMap[category] = k 

alert(categoryMap['puzzles']) 

Demo

使用这种实现,你需要遍历结构只有一次达阵(加上可能的,如果改变的ShopMap更新)。随着你的和流行病的回答,你必须循环每次你需要做这种特定类型的查找。如果你做这个操作很多,它可能会有所作为。另一方面,如果你的shopMap真的很大(比如成千上万的条目),那么我的实现将占用更多的内存。

根据你想要做到这一点的强健程度,你可能想把它变成一个类,并通过类的接口进行任何操作。你需要addCategory和deleteCategory方法以及getStoreFromCategory方法,这实际上是我们上面实现的。这种面向对象的方法会隐藏内部数据结构/实现,以便稍后可以改变实现来优化内存或速度。

+0

这是一个很好的解决方案,因为查找的成本只会降低到一个属性访问。但是应该指出的是,为第一次实现做这件事可能是一个过早优化的情况,至少没有太多的信息,它可能稍后会咬(例如,我们不知道'shopMap'是否可以改变,并且在这种情况下'categoryMap'也应该被更新)。我会说最好先做一个天真的实现,只有当性能很差,并且在分析后,发现店铺查找是性能拖延,那么可以实现这样的解决方案:) – epidemian

+0

谢谢。是的,在这个阶段,这可能是不成熟的优化,如果我发现我反复使用该操作,我会记住它。谢谢。 –

+0

是的,我倾向于构建大型的CoffeeScript库和应用程序,所以我有一种非常面向对象的思维方式。我的第一种方法是将实现隐藏在Class接口后面,我可能会首先使用流行病的实现。从Class开始的优点是,如果稍后优化实现,则不需要更改客户端代码。 当然,根据您的具体情况,将它放在一个班级中可能会过度工程。 –