何时应该使用Haskell的Data.Map来支持元组列表?

时间:2012-12-13 18:28:50

标签: performance haskell

最近我需要比较两组历史数据。由于其中一个中有时缺少一两天而我想要精确,我决定创建一个包含所有可能日期的列表和两个包含日期和属于两个集合的相应值的元组列表。然后我将后面的列表更改为Map以改进日期查找。

我的想法是尝试在Map ped列表中查找完整日期列表中的每个日期,并创建(date, value1, value2)的“三元组”列表,其中仅包含两个数据集都有日期的日期和一个价值。然后我可以将它们写入文件并正确比较它们。

请不要修改该代码,仅包括良好的测量

这是代码(它根本不是最优的,但对于那个小任务,它很好地完成了它的工作):

import qualified Data.Map as M
import Data.List (transpose)
import Data.Maybe (fromJust)

main = do
    dts     <- readFile "dates.txt"
    cts1    <- readFile "eu.txt"
    cts2    <- readFile "usa.txt"
    let
        dates  = lines dts
        cols1  = transpose $ map words $ lines cts1
        cols2  = transpose $ map words $ lines cts2
        prs1   = zip (head cols1) (last cols1)
        prs2   = zip (head cols2) (last cols2)
        map1   = M.fromList prs1
        map2   = M.fromList prs2
        trips  = map fromJust (filter (/=Nothing) (map (\date -> getTrips date map1 map2) dates))
        cols3  = map (\(a,b,c) -> [a,b,c]) trips
        result = unlines $ map unwords $ cols3
    writeFile "trips.txt" result

getTrips :: String -> M.Map String String -> M.Map String String -> Maybe (String, String, String)
getTrips date map1 map2
    | is1 /= Nothing && is2 /= Nothing    = Just (date, fromJust is1, fromJust is2)
    | otherwise                           = Nothing
    where
        is1 = M.lookup date map1
        is2 = M.lookup date map2

TL; DR:代码有效(虽然我很乐意听到一些意见/建议),但我有一些问题:

  • 只有大约2000个日期,因此我对表现并不在意(你可以看到我到处都在使用String);然后使用Data.Map过度杀伤? 何时Data.Map优先于元组列表?
  • Map是根据String s的元组创建的 - 如果密钥始终为数字,那么它是正常的还是,以便平衡和查找正常工作? < / LI>

1 个答案:

答案 0 :(得分:5)

  

只有约2000个日期,因此我并不在意   性能(你可以看到我到处使用Strings);是   使用Data.Map一个矫枉过正的呢?什么时候应该首选Data.Map   在元组列表?

您应该使用适合您的问题和性能/编程时间限制的数据结构,因此使用Map可能是一个好主意。也许在您的情况下,如果您的数据已经订购,您可以完成

union [] _ = []
union _ [] = []
union xss@((dx,vx):xs) yss@((dy,vy):ys) = 
    case compare dx dy of
         EQ -> (dx, vx, vy) : union xs ys
         GT -> union xss ys
         LT -> union xs yss
  

地图是从字符串的元组创建的 - 它是好的还是应该的   key始终为数字,以便平衡和查找起作用   正常?

不,如果您的代码类型检查您的Map将正常工作(与您定义Ord实例的方式不同)。但正如CA McCann所暗示的那样,如果你的密钥是列表,trie可能更合适,特别是如果密钥前缀之间有很多重叠(看看列表上的Ord实例是如何实现的,并想象一下将“abcdx”,“abcdy”和“abcdz”键插入Map与trie结构以说服自己的必须进行的操作次数。