从数据和键创建列表

时间:2012-11-23 11:19:27

标签: list haskell key list-comprehension

我对Haskell有疑问。我想知道如何从两个列表创建数据列表,一个列表包含数据,另一个列表包含一些键值。我将用一个例子来解释它:

给出两个列表:[('a', "red"), ('b', "blue"), ('c', "green")][('a','b'), ('b', 'c'), ('c','a')]。现在我想用第一个列表中给出的颜色更改第二个列表的值。因此该函数应返回[("red","blue"), ("blue","green"), ("blue","red")]

我在考虑列表理解,但我对Haskell很新,我不知道应该怎么做。或者有更简单的方法吗?

这可能是一个愚蠢的问题,但如果有人能给我一个例子,我可能会更习惯Haskell的思考过程。

3 个答案:

答案 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 
> []