Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List/Object searching in CoffeeScript

I'm trying to get my head around using CoffeeScript comprehensions as efficiently as possible. I think I have basic mapping down -- turning one list into another -- but searching still seems verbose to me.

Say I have a map of items to shops:

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

and, given an item, I want to find out which shop it's in. What's the best way of doing that in CoffeeScript?

Here's how I could do in in 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;
         }
      }
  }
}

I used a function to allow it to quickly break out of the loops with the return statement, instead of using breaks, but the function is kind of fugly as this is only being used once.

So is there a shorter CS equivalent preferably one that doesn't require creating a new function?

like image 406
Sam Fen Avatar asked Jan 16 '23 08:01

Sam Fen


2 Answers

You can try this:

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

If you really want to try with a list comprehension, this is equivalent:

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

But i think the first one reads better (and also doesn't need to generate an intermediate array for the results). This would be a better approach IMO if you wanted to find all shops for a given item:

findShops = (item) ->
  shop for shop, items of shopMap when item in items
like image 135
epidemian Avatar answered Jan 18 '23 23:01

epidemian


If this is a common operation, you might be better off creating an intermediate data structure up front and doing the lookup directly.

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

With this implementation you need to loop through the structure only once up front (plus possibly update it if shopMap changes). With yours and epidemian's answer, you have to loop every time you need to do this particular type of lookup. If you do this operation a lot, it could make a difference. On the other hand, if your shopMap is really large (like thousands of entries), then my implementation will take up more memory.

Depending upon how robust you want to make this, you might want to turn it into a Class and have any operations on it occur through the Class' interface. You'd need addCategory and deleteCategory methods as well as a getStoreFromCategory method, which is essentially what we are implementing above. This object-oriented approach would hide the internal data-structure/implementation so you could later alter the implementation to optimize for memory or speed.

like image 35
Larry Maccherone Avatar answered Jan 18 '23 22:01

Larry Maccherone