使用isInfixOf将字符串列表与字符串匹配的模式

时间:2018-09-13 13:03:57

标签: haskell

你好,我是haskell的初学者,我在比较/匹配具有给定字符串作为参数的集合列表中的字符串时遇到问题。

我想要实现的是:

我有一个清单

colorTypes = ["red" , "blue" ,"yellow" , "green" ]

我要做的是使用Data.List中的isInfixOf函数,使一个函数将给定的字符串与List的每个元素进行比较,并根据isInfixOf的结果返回一个模式

如果我使用函数的示例:

getColorData colorTypes "red" 

它应该返回

[1, 0, 0, 0]

我尝试过的是:

import Data.List 

getColorData  :: [String] -> String -> [Int]
getColorData (g:h:j:k) str 
    | isInfixOf g str = [1, 0, 0, 0]
    | isInfixOf h str = [0, 1, 0, 0]
    | isInfixOf j str = [0, 0, 1, 0]
    | isInfixOf k str = [0, 0, 0, 1]
    | otherwise = []

我收到错误:使用此函数解析模式为:isInfixOf中的错误

我也尝试了这种情况

 getColorData  :: [String] -> String -> [Int]
 getColorData (g:h:j:k) str = case (g:h:j:k) of
                         isInfixOf g str -> [1, 0, 0, 0]
                         isInfixOf h str -> [0, 1, 0, 0]
                         isInfixOf j str -> [0, 0, 1, 0]
                         isInfixOf k str -> [0, 0, 0, 1]

这也行不通,并且出现无法匹配的类型错误。

我不知道我的方法是否错误,或者是否有其他方法可以得到我想要的东西,但我会感谢您的帮助

1 个答案:

答案 0 :(得分:2)

问题出在这里,您使用以下模式进行匹配:

getColorData (g:h:j:k) str

此处ghj是列表的 heads (第一元素),而k >列表的(其余项)。因此k的类型为[String]不是 String

我们可以使用[g,h,j,k]来修复它,它是四个元素的列表:

getColorData  :: [String] -> String -> [Int]
getColorData [g,h,j,k] str 
    | isInfixOf g str = [1, 0, 0, 0]
    | isInfixOf h str = [0, 1, 0, 0]
    | isInfixOf j str = [0, 0, 1, 0]
    | isInfixOf k str = [0, 0, 0, 1]
    | otherwise = []

但它仍然不是真正好的设计。由于对于包含少于或多于四个元素的列表,此函数将出错。我也不确定使用isInfixOf条件是否是个好主意:这意味着列表的顺序有时可以确定结果是什么:两个元素被交换的列表可能会导致不同。最后,代码是非常重复的(不遵循 D 而不是 R 重复 Y 我们自己的原则)。

一个更优雅的版本可能是:

getColorData :: Eq a => [a] -> [a] -> Maybe [Int]
getColorData [] _ = Nothing
getColorData (x:xs) s | isInfixOf x s = Just (1: map (const 0) xs)
                      | otherwise = fmap (0:) (getColorData xs s)

在这里,我们让它适用于两个a具有相等关系的任何类型a。此外,它适用于所有长度的列表。如果找不到元素,它将返回Nothing,并返回Just ee实体向量,并以列表的长度作为维数。