最近我需要比较两组历史数据。由于其中一个中有时缺少一两天而我想要精确,我决定创建一个包含所有可能日期的列表和两个包含日期和属于两个集合的相应值的元组列表。然后我将后面的列表更改为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:代码有效(虽然我很乐意听到一些意见/建议),但我有一些问题:
String
);然后使用Data.Map
过度杀伤? 何时Data.Map
优先于元组列表? Map
是根据String
s的元组创建的 - 如果密钥始终为数字,那么它是正常的还是,以便平衡和查找正常工作? < / LI>
答案 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结构以说服自己的必须进行的操作次数。