left :: [String]->[Char]->Char
left [] _ = []
left (x:xs) (head xs) = x -- it says error at head
我使用了正确的括号,但仍然出现解析错误。顺便说一句,我正在尝试获取列表中的先前元素,例如[["A"],["B"],["C"],["D"],["E"]]
.也许我还有其他一些错误。请纠正我.
第二个问题是如何选择以前的元素以前的索引字符。例如给函数这个列表[["J","O","H","N"],["A","L","I","C","E"]]和"C",我想期望得到"H"。我的意思是"C"是第二个元素的第4个索引,"H"是以前的元素第三个索引。提前感谢
如果我理解你很好,你需要一个函数,它在String
列表中找到一个字符,并在前面的索引处返回前面字符串的字符。
像这样:
f ["JOHN", "ALICE"] 'C' == 'H'
首先,您需要知道Char
文字在Haskell('A'
)中用简单引号分隔,String
文字用双引号("ABC"
)分隔。
因为在Haskell中String
是[Char]
的别名,"ABC"
等价于['A', 'B', 'C']
。
也就是说,在Haskell中,你不能定义这样的函数:f a a = stuff
。全康会抱怨a
被多次定义。 因此,要检查两个参数是否具有某些属性,您需要保护模式。
所以我会像这样写你的第一个函数:
left :: [String] -> String -> String
left [] _ = ""
left [x] _ = ""
left (x1:x2:xs) str
| x2 == str = x1
| otherwise = left (x2:xs) str
对于你的第二个问题:
import Data.List
f :: [String] -> Char -> Maybe Char
f [] _ = Nothing
f [a] _ = Nothing
f (x1:x2:xs) c
| Just i <- elemIndex c x2 = Just $ x1 !! (i-1)
| otherwise = f (x2:xs) c
笔记:
left
还应返回Maybe String
,以防找不到str
或未找到或首先找到。f
不检查x1
是否真的足够长- 通常在 Haskell 中,list 参数是最后一个,以允许咖喱。
编辑:
一种更聪明的zip
方法(在模块Data.List
中)。
f :: [String] -> Char -> Maybe Char
f [] _ = Nothing
f [_] _ = Nothing
f (x1:"":xs) c = f xs c
f (x1:x2:xs) c = f' (zip x1 (tail x2))
where f' [] = f (x2:xs) c
f' ((a,b):l) = if b == c then a else f' l
此版本不会崩溃。它将返回满足"是第 n 个字符串中的第 m 个字符,而第 (n+1)个字符串中的 (m+1)个字符"的第一个字符是c
。结果将被包装在Maybe
(Just 'H'
)。否则,它返回Nothing
(Maybe
大致是 Haskell 的可为空类型)。
zip
是一个将两个列表合并为一个对列表的函数:
zip ['a', 'b', 'c'] [1, 2] == [('a', 1), ('b', 2)]
生成的列表的大小是最小的列表之一。所以在示例中,发生的情况是:
zip "JOHN" (tail "ALICE") == [('J','L'), ('O', 'I'), ('H', 'C'), ('N', 'E')]
然后,您只需检查第二个字符是否是搜索的字符,然后返回该对的第一个字符。
要访问"上一个"列表元素,您必须使用不同的递归。 例如
foo [] = baseCase
foo [x] = onlyOneElement x
foo (x1:x2:xs) = use x1 x2 (foo (x2:xs))
调用foo [1,2,3,4,5]
时,您可以访问x1=1, x2=2
。递归时,您将可以访问x1=2, x2=3
,依此类推。因此,您可以将x2
视为"当前"元素,x1
是前一个元素。