[英]Apply a function to every element in a list to every element in another list - Haskell
我的最终目标是确定列表y是否包含列表x的所有元素(我正在检查x是否是y的子集)
subset x y =
and [out | z <- x
, out <- filter (==z) y ]
这不起作用,我知道这是因为z仍然是列表。 我试图弄明白这一点。
我想我可能必须使用elem
函数,但是我不确定如何将x拆分为可以通过y分别比较的字符。
我很to愧地说我已经在这个简单的问题上工作了一个半小时。
检查xs
所有元素是否都是ys
元素非常简单。 遍历xs
,对于每个元素,检查它是否在ys
:
subset xs ys = all (\x -> elem x ys) xs
您还可以使用列表差异功能( \\\\
)。 如果您具有列表y和列表x,并且要检查x的所有元素都在y中,则x \\\\ y
将返回一个新列表,其中包含x的元素不在y中。 如果x的所有元素都在y中,则返回的列表将为空。
例如,如果列表y为[1,2,3,4,5],列表x为[2,4],则可以执行以下操作:
Prelude> [2,4] \\ [1,2,3,4,5]
[]
如果列表y为[1,2,3,4,5],列表x为[2,4,6],则:
Prelude> [2,4,6] \\ [1,2,3,4,5]
[6]
推断子集的简单方法是使用集合作为数据类型。
import qualified Data.Set as S
subset :: Ord a => [a] -> [a] -> Bool
subset xs ys = S.isSubsetOf (S.fromList xs) (S.fromList ys)
然后就这么简单:
*Main> subset [1..5] [1..10]
True
*Main> subset [0..5] [1..10]
False
让我们将其分解为两个子问题:
对于第一个子问题,已经有一个库函数:
elem :: (Eq a, Foldable t) => a -> t a -> Bool
列表是Foldable
类型,因此您可以将此函数与t
列表一起使用,并且它将具有以下类型:
elem :: (Eq a) => a -> [a] -> Bool
练习:编写自己的elem
版本,专门用于处理列表(现在不用担心Foldable
东西)。
所以现在,要解决第二个问题,第一步就是:
-- For each element of `xs`, test whether it's an element of `ys`.
-- Return a list of the results.
notYetSubset :: Eq a => [a] -> [a] -> [Bool]
notYetSubset xs ys = map (\x -> elem x ys) xs
之后,我们需要从单个布尔结果列表中删除一个布尔值。 有一个标准的库函数也可以做到这一点:
-- Return true if and only if every element of the argument collection is
-- is true.
and :: Foldable t => t Bool -> Bool
锻炼:编写自己的and
版本,专门用于列出:
myAnd :: [Bool] -> Bool
myAnd [] = _fillMeIn
myAnd (x:xs) = _fillMeIn
使用这些工具,现在我们可以编写subset
:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = and (map (\x -> elem x ys) xs)
尽管经验丰富的Haskeller可能会这样写:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = every (`elem` ys) xs
{- This:
(`elem` ys)
...is a syntactic shortcut for this:
\x -> x elem ys
-}
...其中every
都是另一个标准库函数,这只是map
和and
组合的快捷方式:
-- Apply a boolean test to every element of the list, and
-- return `True` if and only if the test succeeds for all elements.
every :: (a -> Bool) -> [a] -> Bool
every p = and . map p
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.