假设我有数组:
A = "ABACUS"
B = "YELLOW"
它们是压缩的:Pairing = zip A B
我还有一个函数Connect :: Char -> [(Char,Char)] -> [(Char,Char,Int)]
我想要做的是给出一个像A这样的字符,找到它在第一个字符串中的位置的索引,并在第二个字符串中的相同位置返回字符,以及例如如果我做Connect 'A' Pairing
我想要(A,Y,0)和(A,L,2)作为结果。
我知道我能做到
pos = x!!map fst pairing
检索位置。并fnd = findIndices (==pos) map snd pairing
得到第二个字符串中的这个位置,但是在Haskell中我将如何在整个数据集上执行此操作(就像我使用for循环一样)以及如何获得输出?
答案 0 :(得分:4)
要完全按照你的要求(但将函数名称的首字母更正为小写),我可以定义
connect :: Char -> [(Char,Char)] -> [(Char,Char,Int)]
connect c pairs = [(a,b,n)|((a,b),n) <- zip pairs [0..], a == c]
所以,如果
pairing = zip "ABACUS" "YELLOW"
我们得到了
ghci> connect 'A' pairing
[('A','Y',0),('A','L',2)]
但是,我认为使用zip3
拉链一次而不是两次更简洁:
connect3 :: Char -> String -> String -> [(Char,Char,Int)]
connect3 c xs ys = filter (\(a,_,_) -> a==c) (zip3 xs ys [0..])
相当于
connect3' c xs ys = [(a,b,n)| (a,b,n) <- zip3 xs ys [0..], a==c]
他们都按你的意愿工作:
ghci> connect3 'A' "ABACUS" "YELLOW"
[('A','Y',0),('A','L',2)]
ghci> connect3' 'A' "ABACUS" "AQUAMARINE"
[('A','A',0),('A','U',2)]
在评论中,你说过你想要以相反的方式获得对比赛。
这一次,使用monadic do
表示法最方便,因为列表是monad的一个例子。
connectEither :: (Char,Char) -> String -> String -> [(Char,Char,Int)]
connectEither (c1,c2) xs ys = do
(a,b,n) <- zip3 xs ys [0..]
if a == c1 then return (a,b,n) else
if b == c2 then return (b,a,n) else
fail "Doesn't match - leave it out"
我使用fail
函数省略了不匹配的函数。从if
,if
和fail
开始的三条线越来越缩进,因为它们实际上是从哈斯克尔的角度来看的一行。
ghci> connectEither ('a','n') "abacus" "banana"
[('a','b',0),('a','n',2),('n','u',4)]
在这种情况下,它没有包含('n','a',2)
,因为它只检查一种方式。
我们可以通过重用现有功能来实现两种方式:
connectBoth :: (Char,Char) -> String -> String -> [(Char,Char,Int)]
connectBoth (c1,c2) xs ys = lefts ++ rights where
lefts = connect3 c1 xs ys
rights = connect3 c2 ys xs
给了我们想要的一切:
ghci> connectBoth ('a','n') "abacus" "banana"
[('a','b',0),('a','n',2),('n','a',2),('n','u',4)]
但不幸的是不止一次:
ghci> connectBoth ('A','A') "Austria" "Antwerp"
[('A','A',0),('A','A',0)]
因此,我们可以使用nub
中的Data.List
来摆脱这种情况。 (在文件顶部添加import Data.List
。)
connectBothOnce (c1,c2) xs ys = nub $ connectBoth (c1,c2) xs ys
给
ghci> connectBothOnce ('A','A') "ABACUS" "Antwerp"
[('A','A',0),('A','t',2)]
答案 1 :(得分:1)
我建议不要将列表压缩在一起,因为这只会使elemIndices
中的函数Data.List
变得更加困难。然后,您可以直接使用索引列表从第二个列表中获取值。
答案 2 :(得分:1)
您可以使用另一个zip
添加索引,然后对给定字符进行过滤并将元组转换为三元组。特别是因为这种重新包装,列表理解似乎是合适的:
connect c pairs = [(a, b, idx) | ((a, b), idx) <- zip pairs [0..], a == c]