2012-06-18 69 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開始的優點是,如果稍後優化實現,則不需要更改客戶端代碼。 當然,根據您的具體情況,將它放在一個班級中可能會過度工程。 –