簡體   English   中英

從地圖以數據類型提取鍵

[英]Extract keys from map in a data type

我試圖在具有許多字段的數據類型中返回具有特定Status鍵。 我嘗試了幾件事,但是什么都沒編譯! 有人知道我可以使用的小費嗎?

data Configuration v = Configuration {
configurationMap   :: Map.Map v Status,
configurationGraph :: Graph v
}

verticesByStatus :: Ord v => Status -> Configuration v -> [v]
verticesByStatus  ???

也許有一種更優雅的表達方式,但這是一個解決方案:

  verticesByStatus status (Configuration map graph) = fst <$> (filter ((== status) . snd) $ M.assocs map)

那么這是怎么回事? 首先,我們對配置參數進行模式匹配以提取其兩個組成部分,並將其分配給變量mapgraph 現在讓我們分解右側:

  fst <$> (filter ((== status) . snd) $ Map.assocs map)
                                            ^-- This comes from the Data.Map package and splits a map into a list of tuples of key/value pairs. 
                            ^-- Here, we filter our new list of key/values based on the values, and find only those that match the input status 
  ^-- Last, we fmap the function fst over the whole list to extract only the keys that match your given status

表達此功能的另一種方法是通過eta簡化將其簡化。 一種方法是使用configurationMap函數提取configurationMap該部分而不是模式匹配:

  verticesByStatus status = fmap fst . filter ((== status) . snd) . Map.assocs . configurationMap

Data.Map有一個映射filter ,可以直接與您的配置映射一起使用:

verticesByStatus :: Ord v => Status -> Configuration v -> [v]
verticesByStatus status = Map.keys . Map.filter (== status) . configurationMap

Map.keys生成地圖中的鍵列表。 (如果你想值的列表,而不是,您可以使用Map.elems或者等價地, toListData.Foldable 。需要注意的是,有些令人混淆,后者是不一樣的Map.toList ,產生密鑰列表值對,就像Map.assocs在jkeuhlen的答案。)

verticesByStatus :: Ord v => Status -> Configuration v -> [v]
verticesByStatus status (Configuration cMap cGraph) =
    [ v
    | v <- vertices cGraph,
      Just(status) == (Map.lookup v cMap)]

一些注意事項:

  • 我選擇避免使用Map.assocs因為它要花費額外的O(n)來運行,您可以在配置映射中獲取值,而無需先將其轉換為元組列表(請參閱Map docs )。

  • 我選擇了列表理解功能,而不是將mapfilter組合在一起而不是出於個人喜好,因為我發現它更易於閱讀(在閱讀本文后我發現了這一點

  • 相反,我們可以檢查查詢是否返回了JustNothing ,然后在使用fromJustJust情況下提取了該值,但這將是更多的代碼並且可能更難閱讀。 它看起來像:

     verticesByStatus :: Ord v => Status -> Configuration v -> [v] verticesByStatus status (Configuration cMap cGraph) = [ v | v <- vertices cGraph, let vStatus = Map.lookup v cMap, if (isJust vStatus) then (status == (fromJust vStatus)) else False] 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM