4

我试图尽可能有效地使用 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 语句快速跳出循环,而不是使用中断,但是这个函数有点丑陋,因为它只被使用一次。

那么是否有更短的 CS 等效项,最好是不需要创建新函数的等效项?

4

2 回答 2

8

你可以试试这个

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]

但我认为第一个读起来更好(也不需要为结果生成中间数组)。如果您想查找给定商品的所有商店,这将是 IMO 更好的方法:

findShops = (item) ->
  shop for shop, items of shopMap when item in items
于 2012-06-18T19:36:04.370 回答
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'])

演示

使用此实现,您只需要预先循环一次结构(如果 shopMap 更改,还可能更新它)。使用您和流行病的答案,每次需要进行这种特定类型的查找时,您都必须循环。如果您经常执行此操作,可能会有所作为。另一方面,如果您的 shopMap 真的很大(如数千个条目),那么我的实现将占用更多内存。

根据您想要使其变得多么健壮,您可能希望将其变成一个类并通过类的接口对其进行任何操作。您需要 addCategory 和 deleteCategory 方法以及 getStoreFromCategory 方法,这基本上就是我们在上面实现的。这种面向对象的方法将隐藏内部数据结构/实现,以便您以后可以更改实现以优化内存或速度。

于 2012-06-18T22:31:01.250 回答