以语义方式填充元组列表
Populating a list of tuples in a semantic way
我正在编写一段代码,其中我必须处理元组列表,其中 "keys"(元组的 fst
s)的顺序和名称都匹配某个模板.我通过验证和(如果需要)根据输入生成有效列表来实现容错。
这是我的意思的一个例子:
给定键模板 ["hello", "world", "this", "is", "a", "test"]
和一个列表 [("hello", Just 1), ("world", Just 2), ("test", Just 3)]
,将其传递给我的函数 validate
将导致其验证失败 - 因为密钥与模板不匹配。
验证失败后,我想生成一个新列表,看起来像 [("hello", Just 1), ("world", Just 2), ("this", Nothing), ("is", Nothing), ("a", Nothing), ("test", Just 3)]
。
我尝试使用(不完整的)列表理解来执行最后一步:
[(x, y) | x <- template, y <- l]
(显然,这缺少将空条目替换为 Nothing
的步骤,并且在假设输入类型为 [(String, Maybe Int)]
的情况下工作)。
最简单的语义方法是什么?
你本质上想要映射一个函数到你的字符串列表(你称之为"template"),即
的函数
- 接受一个字符串
xs
,
- returns
(xs, Just n)
如果一个整数 n
关联到 xs
在您的 "list to validate",
(xs, Nothing)
否则。
这是一种可能的方法:
import Data.List ( lookup )
import Control.Monad ( join )
consolidate :: [String] -> [(String, Maybe Int)] -> [(String, Maybe Int)]
consolidate temp l = map (\xs -> (xs, join $ lookup xs l)) temp
但是,如果您构建 Map
保存关联列表("list to validate")的键值对,您的查找速度会更快:
import qualified Data.Map as M
import Data.Maybe (maybe)
consolidate :: [String] -> [(String, Maybe Int)] -> [(String, Maybe Int)]
consolidate temp l = map (\cs -> (cs, M.lookup cs $ fromList' l)) temp
fromList' :: Ord a => [(a, Maybe b)] -> M.Map a b
fromList' xs = foldr insertJust M.empty xs
insertJust :: Ord a => (a, Maybe b) -> M.Map a b -> M.Map a b
insertJust (xs, maybeVal) mp = maybe mp (\n -> M.insert xs n mp) maybeVal
在 GHCi 中:
λ> let myTemplate = ["hello", "world", "this", "is", "a", "test"]
λ> let myList = [("hello", Just 1), ("world", Just 2), ("test", Just 3)]
λ> consolidate myTemplate myList
[("hello",Just 1),("world",Just 2),("this",Nothing),("is",Nothing),("a",Nothing),("test",Just 3)]
我正在编写一段代码,其中我必须处理元组列表,其中 "keys"(元组的 fst
s)的顺序和名称都匹配某个模板.我通过验证和(如果需要)根据输入生成有效列表来实现容错。
这是我的意思的一个例子:
给定键模板 ["hello", "world", "this", "is", "a", "test"]
和一个列表 [("hello", Just 1), ("world", Just 2), ("test", Just 3)]
,将其传递给我的函数 validate
将导致其验证失败 - 因为密钥与模板不匹配。
验证失败后,我想生成一个新列表,看起来像 [("hello", Just 1), ("world", Just 2), ("this", Nothing), ("is", Nothing), ("a", Nothing), ("test", Just 3)]
。
我尝试使用(不完整的)列表理解来执行最后一步:
[(x, y) | x <- template, y <- l]
(显然,这缺少将空条目替换为 Nothing
的步骤,并且在假设输入类型为 [(String, Maybe Int)]
的情况下工作)。
最简单的语义方法是什么?
你本质上想要映射一个函数到你的字符串列表(你称之为"template"),即
的函数- 接受一个字符串
xs
, - returns
(xs, Just n)
如果一个整数n
关联到xs
在您的 "list to validate",(xs, Nothing)
否则。
这是一种可能的方法:
import Data.List ( lookup )
import Control.Monad ( join )
consolidate :: [String] -> [(String, Maybe Int)] -> [(String, Maybe Int)]
consolidate temp l = map (\xs -> (xs, join $ lookup xs l)) temp
但是,如果您构建 Map
保存关联列表("list to validate")的键值对,您的查找速度会更快:
import qualified Data.Map as M
import Data.Maybe (maybe)
consolidate :: [String] -> [(String, Maybe Int)] -> [(String, Maybe Int)]
consolidate temp l = map (\cs -> (cs, M.lookup cs $ fromList' l)) temp
fromList' :: Ord a => [(a, Maybe b)] -> M.Map a b
fromList' xs = foldr insertJust M.empty xs
insertJust :: Ord a => (a, Maybe b) -> M.Map a b -> M.Map a b
insertJust (xs, maybeVal) mp = maybe mp (\n -> M.insert xs n mp) maybeVal
在 GHCi 中:
λ> let myTemplate = ["hello", "world", "this", "is", "a", "test"]
λ> let myList = [("hello", Just 1), ("world", Just 2), ("test", Just 3)]
λ> consolidate myTemplate myList
[("hello",Just 1),("world",Just 2),("this",Nothing),("is",Nothing),("a",Nothing),("test",Just 3)]