1

我有一个关于 Haskell 的问题。我想知道如何从两个列表中创建一个数据列表,一个带有数据,另一个带有一些键值。我会用一个例子来解释它:

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

我正在考虑列表理解,但我对 Haskell 很陌生,我不知道该怎么做。或者有没有更简单的方法来做到这一点?

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

4

3 回答 3

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
[…]
于 2012-11-23T12:15:30.883 回答
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)

于 2012-11-23T11:42:13.717 回答
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 
> []
于 2012-11-23T18:15:08.800 回答