在CoffeeScript中进行列表/对象搜索

时间:2012-06-18 19:10:13

标签: coffeescript list-comprehension

我正试图尽可能高效地使用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等价物,最好不需要创建新函数?

2 个答案:

答案 0 :(得分: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给定项目,这将是一个更好的方法IMO:

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

答案 1 :(得分: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非常大(比如成千上万的条目),那么我的实现会占用更多的内存。

根据您想要的强大程度,您可能希望将其转换为Class,并通过Class'接口对其进行任何操作。您需要addCategory和deleteCategory方法以及getStoreFromCategory方法,这实际上就是我们在上面实现的方法。这种面向对象的方法会隐藏内部数据结构/实现,因此您可以在以后更改实现以优化内存或速度。