我对Haskell有疑问。我想知道如何从两个列表创建数据列表,一个列表包含数据,另一个列表包含一些键值。我将用一个例子来解释它:
给出两个列表:[('a', "red"), ('b', "blue"), ('c', "green")]
和[('a','b'), ('b', 'c'), ('c','a')]
。现在我想用第一个列表中给出的颜色更改第二个列表的值。因此该函数应返回[("red","blue"), ("blue","green"), ("blue","red")]
。
我在考虑列表理解,但我对Haskell很新,我不知道应该怎么做。或者有更简单的方法吗?
这可能是一个愚蠢的问题,但如果有人能给我一个例子,我可能会更习惯Haskell的思考过程。
答案 0 :(得分:4)
另一种方法是使用Map
import Data.Maybe (mapMaybe)
import Data.Map (lookup
,fromList)
import Prelude hiding (lookup)
main :: IO ()
main = do
let a = [('a', "red"), ('b', "blue"), ('c', "green")]
b = [('a','b'), ('b', 'c'), ('c','a')]
table = fromList a
print $ mapMaybe (maybePair . (\(x,y) -> (x `lookup` table,
y `lookup` table ))) b
maybePair :: (Maybe a, Maybe b) -> Maybe (a,b)
maybePair (Just x,Just y) = Just (x, y)
maybePair _ = Nothing
借助箭头,最后一个匿名函数可以压缩到
import Control.Arrow ((***))
[…]
main :: IO ()
main = do
let a = [('a', "red"), ('b', "blue"), ('c', "green")]
b = [('a','b'), ('b', 'c'), ('c','a')]
table = fromList a
f x = x `lookup` table
print $ mapMaybe (maybePair . (f *** f)) b
[…]
答案 1 :(得分:2)
-- second element from first (head) dropping tuples with bad key
color :: Eq a => a -> [(a, b)] -> b
color c = snd.head.dropWhile ((/=c).fst)
recolor a b = map (\(x, y) -> (color x a, color y a)) b
运行
Prelude> recolor [('a', "red"), ('b', "blue"), ('c', "green")] [('a','b'), ('b', 'c'), ('c','a')]
[("red","blue"),("blue","green"),("green","red")]
如果您认为第一个列表中找不到第二个列表的元素。你可以写
color :: Eq b => b -> [(b, a)] -> Maybe a
color c = fmap snd.listToMaybe.dropWhile ((/=c).fst)
然后
Prelude> recolor [('a',"red"),('b',"blue"),('c',"green")] [('a','h'),('u','c'),('c','a')]
[(Just "red",Nothing),(Nothing,Just "green"),(Just "green",Just "red")]
(您需要import Data.Maybe (listToMaybe)
)
答案 2 :(得分:0)
另一种解决方案,无需导入任何库,但使用尾递归:
keyColor = [('a', "red"), ('b', "blue"), ('c', "green")]
keys = [('a','b'), ('b', 'c'), ('c','a')]
colors [] _ = [] -- no keys returns the empty list
colors _ [] = [] -- no colors returns the empty list
colors xs ys = colors_helper (xs, ys, []) -- tail recursion
colors_helper ([], _, acc) = acc
colors_helper (((k1, k2):xs), ys, acc) =
colors_helper (xs, ys, acc ++ [(color (k1, ys), color (k2, ys))])
where
-- converts value to color
color (val, ys) = snd $ head $ filter ( \(k, v) -> k == val ) ys
试验:
> colors keys keyColor
> [("red","blue"),("blue","green"),("green","red")]
> colors keys []
> []
> colors [] keyColor
> []