Haskell 如何检查(字符串对列表和(字符串列表))中的字符串?
我有一个叫做“样本”的数据,定义为Haskell 如何检查(字符串对列表和(字符串列表))中的字符串?,haskell,Haskell,我有一个叫做“样本”的数据,定义为 data Sample = Test1 (String,[[String]]) | Test2 (String,[[String]]) 然后我创建一个名为“Samples”的列表[Sample],比如 现在,我需要检查“Sample3”下是否存在“aborts”。我有一个基本的 我知道如何做,但我不知道如何在Haskell中实现它 我的想法是 check:: String -> [String] -> [Sample]
data Sample = Test1 (String,[[String]])
| Test2 (String,[[String]])
然后我创建一个名为“Samples”的列表[Sample],比如
现在,我需要检查“Sample3”下是否存在“aborts”。我有一个基本的
我知道如何做,但我不知道如何在Haskell中实现它
我的想法是
check:: String -> [String] -> [Sample] -> Bool
check samplename result samples =
我可以这样称呼它:
check "Sample3" ["aborts"] Samples
但是我如何实现这个功能呢
我已经这样解决了,但我正在寻找一个更好的版本 我的版本是:
check:: String -> [String] -> [Sample] -> Bool
check samplename result samples =
if( "True" `elem` final )
then True
else False
where
final = [x | sample <- samples,
x <- [ case sample of
Test1 (name,res) =
if name == samplename && (result `elem` res)
then "True"
else "False"
Test2 (name, res) = "False"]]
check::String->[String]->[Sample]->Bool
检查samplename结果样本=
if(“True”`elem`final)
那是真的
否则错误
哪里
final=[x | sample这应该可以做到:
data Sample = Test1 String [[String]]
| Test2 String [[String]]
sampleName :: Sample -> String
sampleName (Test1 name _) = name
sampleName (Test2 name _) = name
getData :: Sample -> [[String]]
getData (Test1 _ samples) = samples
getData (Test2 _ samples) = samples
check :: String -> [String] -> [Sample] -> Bool
check name needle samples = any doCheck samples
where
doCheck s = if sampleName s == name
then needle `elem` getData s
else False
如果所有名称都应该是不同的,则可以更快地中止搜索:
check2 :: String -> [String] -> [Sample] -> Bool
check2 name needle samples = go samples
where
go [] = False
go (s:ss) = if sampleName s == name
then needle `elem` getData s
else go ss
测试:
*Main> check "Sample3" ["aborts"] tst
True
对您的版本的评论:
data Sample = Test1 (String,[[String]])
| Test2 (String,[[String]])
这里不需要元组(参见我的代码)
一般来说,如果expr那么True或者False总是可以替换为expr
。为什么使用字符串作为布尔值
final = [x | sample <- samples,
x <- [ case sample of
Test1 (name,res) -> if name == samplename
&& (result `elem` res)
then "True" else "False"
Test2 (name, res) -> "False"]]
这应该可以做到:
data Sample = Test1 String [[String]]
| Test2 String [[String]]
sampleName :: Sample -> String
sampleName (Test1 name _) = name
sampleName (Test2 name _) = name
getData :: Sample -> [[String]]
getData (Test1 _ samples) = samples
getData (Test2 _ samples) = samples
check :: String -> [String] -> [Sample] -> Bool
check name needle samples = any doCheck samples
where
doCheck s = if sampleName s == name
then needle `elem` getData s
else False
如果所有名称都应该是不同的,则可以更快地中止搜索:
check2 :: String -> [String] -> [Sample] -> Bool
check2 name needle samples = go samples
where
go [] = False
go (s:ss) = if sampleName s == name
then needle `elem` getData s
else go ss
测试:
*Main> check "Sample3" ["aborts"] tst
True
对您的版本的评论:
data Sample = Test1 (String,[[String]])
| Test2 (String,[[String]])
这里不需要元组(参见我的代码)
一般来说,如果expr那么True或者False总是可以替换为expr
。为什么使用字符串作为布尔值
final = [x | sample <- samples,
x <- [ case sample of
Test1 (name,res) -> if name == samplename
&& (result `elem` res)
then "True" else "False"
Test2 (name, res) -> "False"]]
如果我们在高层次上考虑检查必须做什么,我们知道它必须检查样本的每个元素,以查看测试“Sample3”是否包含任何(或全部,我不清楚您的意思是什么)字符串结果
所以我们知道我们需要递归,我们可以从函数的大致轮廓开始:
check :: String -> [String] -> [Sample] -> Bool
check samplename result [] = False
check samplename result (x:xs) = ...
因此,当列表为空时,不会出现匹配项,因此我们可以立即返回false。在递归情况下,我们知道需要检查x,如果没有找到匹配项,则继续检查xs。一种可能的方法是使用helper函数检查(您也可以直接内联检查)
好的,那么check做什么呢?它检查数据类型样本以查看是否存在任何匹配。我们知道样本有两个构造函数,Test1和Test2所以check应该是这样的
check' :: Sample -> Bool
check' (Test1 (name, values)) = ...
check' (Test2 (name, values)) = ...
我们要做的第一件事是测试name的值,看看它是否与samplename匹配。我们可以使用警卫轻松地完成这项工作
check' :: Sample -> Bool
check' (Test1 (name, values)) | name == samplename = ...
check' (Test2 (name, values)) | name == samplename = ...
check' _ = False
由于check'是check的子函数,因此check中定义的变量在作用域中,因此我们可以直接引用它们。添加了一个新的大小写来处理名称不匹配的事件
好的,现在的想法是检查结果中的任何(或所有)值是否出现在值中。幸运的是,前奏曲有一个函数可以用于此
elem :: Eq a => a -> [a] -> Bool
该函数现在变为
check' :: Sample -> Bool
check' (Test1 (name, values)) | name == samplename = result `elem` values
check' (Test2 (name, values)) | name == samplename = result `elem` values
check' _ = False
因此,其全部功能是:
check :: String -> [String] -> [Sample] -> Bool
check samplename result [] = False
check samplename result (x:xs) = check' x || check samplename result xs
where check' :: Sample -> Bool
check' (Test1 (name, values)) | name == samplename = result `elem` values
check' (Test2 (name, values)) | name == samplename = result `elem` values
check' _ = False
使用谓词检查列表中的每个元素非常常见,因此prelude具有用于此操作的标准函数。定义检查的一种可能方法是使用函数或和映射。
这通常会导致效率较低的功能,尽管:
check :: String -> [String] -> [Sample] -> Bool
check samplename result samples = or (map check' samples)
where check' :: Sample -> Bool
check' (Test1 (name, values)) | name == samplename = result `elem` values
check' (Test2 (name, values)) | name == samplename = result `elem` values
check' _ = False
通过为数据类型调整替代结构,可以进一步简化该函数,例如
type ID = Int
type Name = String
type Values = [[String]]
data Sample = Test ID Name Values
然后,该函数变为
check :: String -> [String] -> [Sample] -> Bool
check samplename result samples = or (map check' samples)
where check' :: Sample -> Bool
check' (Test _ name values) | name == samplename = result `elem` values
check' _ = False
最后,由于check的结果是Bool,而警卫也是Bool,因此我们可以将check重构为一种更简单的形式,而不需要使用错误案例
check :: String -> [String] -> [Sample] -> Bool
check samplename result samples = or (map check' samples)
where check' :: Sample -> Bool
check' (Test _ name values) = name == samplename && result `elem` values
这种**或(映射…)**模式非常常见,因此也有一个前奏功能any可以实现这一点。检查可以进一步简化为
check :: String -> [String] -> [Sample] -> Bool
check samplename result samples = any check' samples
where check' :: Sample -> Bool
check' (Test _ name values) = name == samplename && result `elem` values
如果我们在高层次上考虑检查必须做什么,我们知道它必须检查样本的每个元素,以查看测试“Sample3”是否包含任何(或全部,我不清楚您的意思是什么)字符串结果
所以我们知道我们需要递归,我们可以从函数的大致轮廓开始:
check :: String -> [String] -> [Sample] -> Bool
check samplename result [] = False
check samplename result (x:xs) = ...
因此,当列表为空时,不会出现匹配项,因此我们可以立即返回false。在递归情况下,我们知道需要检查x,如果没有找到匹配项,则继续检查xs。一种可能的方法是使用helper函数检查(您也可以直接内联检查)
好的,那么check做什么呢?它检查数据类型样本以查看是否存在任何匹配。我们知道样本有两个构造函数,Test1和Test2所以check应该是这样的
check' :: Sample -> Bool
check' (Test1 (name, values)) = ...
check' (Test2 (name, values)) = ...
我们要做的第一件事是测试name的值,看看它是否与samplename匹配。我们可以使用警卫轻松地完成这项工作
check' :: Sample -> Bool
check' (Test1 (name, values)) | name == samplename = ...
check' (Test2 (name, values)) | name == samplename = ...
check' _ = False
由于check'是check的子函数,因此check中定义的变量在作用域中,因此我们可以直接引用它们。添加了一个新的大小写来处理名称不匹配的事件
好的,现在的想法是检查结果中的任何(或所有)值是否出现在值中。幸运的是,前奏曲有一个函数可以用于此
elem :: Eq a => a -> [a] -> Bool
该函数现在变为
check' :: Sample -> Bool
check' (Test1 (name, values)) | name == samplename = result `elem` values
check' (Test2 (name, values)) | name == samplename = result `elem` values
check' _ = False
因此,其全部功能是:
check :: String -> [String] -> [Sample] -> Bool
check samplename result [] = False
check samplename result (x:xs) = check' x || check samplename result xs
where check' :: Sample -> Bool
check' (Test1 (name, values)) | name == samplename = result `elem` values
check' (Test2 (name, values)) | name == samplename = result `elem` values
check' _ = False
使用谓词检查列表中的每个元素非常常见,因此prelude具有用于此操作的标准函数。定义检查的一种可能方法是使用函数或和映射。
这通常会导致效率较低的功能,尽管:
check :: String -> [String] -> [Sample] -> Bool
check samplename result samples = or (map check' samples)
where check' :: Sample -> Bool
check' (Test1 (name, values)) | name == samplename = result `elem` values
check' (Test2 (name, values)) | name == samplename = result `elem` values
check' _ = False
通过为数据类型调整替代结构,可以进一步简化该函数,例如
type ID = Int
type Name = String
type Values = [[String]]
data Sample = Test ID Name Values
然后,该函数变为
check :: String -> [String] -> [Sample] -> Bool
check samplename result samples = or (map check' samples)
where check' :: Sample -> Bool
check' (Test _ name values) | name == samplename = result `elem` values
check' _ = False
最后,由于check的结果是Bool,而警卫也是Bool,因此我们可以将check重构为一种更简单的形式,而不需要使用错误案例
check :: String -> [String] -> [Sample] -> Bool
check samplename result samples = or (map check' samples)
where check' :: Sample -> Bool
check' (Test _ name values) = name == samplename && result `elem` values
这种**或(映射…)**模式非常常见,因此也有一个前奏功能any可以实现这一点。检查可以进一步简化为
check :: String -> [String] -> [Sample] -> Bool
check samplename result samples = any check' samples
where check' :: Sample -> Bool
check' (Test _ name values) = name == samplename && result `elem` values
这是我的解决方案。但我认为你的数据并不代表任何实际问题,如果你想存储像[Sample]这样的东西,你可以很容易地使用Map,它基本上是一个键值列表