我还有另外一个关于从各种来源生成列表的问题。
更新:简化示例
我有一个变量列表
["a", "b", "c"]
和bool值
[False, True].
现在我想要一个列表,其中变量列表的所有子序列都与值列表交叉,因此对于每个条目,变量的子序列列表都包含一组与每个可能值的对。
对于上面的列表,我会得到这个(这个场景的完整列表)。由于空列表不会很好地与其他列表配对,我不关心它是否是结果列表的一部分(可以稍后添加)。
[
[],
[("a", False)],
[("a", True)],
[("b", False)],
[("b", True)],
[("c", False)],
[("c", True)],
[("a", False), ("b", False)],
[("a", False), ("b", True)],
[("a", True), ("b", False)],
[("a", True), ("b", True)],
[("a", False), ("c", False)],
[("a", False), ("c", True)],
[("a", True), ("c", False)],
[("a", True), ("c", True)],
[("b", False), ("c", False)],
[("b", False), ("c", True)],
[("b", True), ("c", False)],
[("b", True), ("c", True)],
[("a", False), ("b", False), ("c", False)],
[("a", False), ("b", False), ("c", True)],
[("a", False), ("b", True), ("c", False)],
[("a", False), ("b", True), ("c", True)],
[("a", True), ("b", False), ("c", False)],
[("a", True), ("b", False), ("c", True)],
[("a", True), ("b", True), ("c", False)],
[("a", True), ("b", True), ("c", True)],
]
如果它只是排列,那么对排列的调用与理解相结合就足够了,但我不知道如何轻松获得子顺序的列表。 我可以使用“调用排列+理解” - 在不同大小的列表上使用 - 但听起来不是很优雅。
对此有直接的解决方案吗?
答案 0 :(得分:3)
import Control.Monad (forM)
import Data.List (subsequences)
solution :: [a] -> [b] -> [[(a, b)]]
solution variables values = do
sequence <- subsequences variables
forM sequence $ \variable -> do
value <- values
return (variable, value)
证明它有效:
>>> mapM_ print $ solution ["a", "b", "c"] [False, True]
[]
[("a",False)]
[("a",True)]
[("b",False)]
[("b",True)]
[("a",False),("b",False)]
[("a",False),("b",True)]
[("a",True),("b",False)]
[("a",True),("b",True)]
[("c",False)]
[("c",True)]
[("a",False),("c",False)]
[("a",False),("c",True)]
[("a",True),("c",False)]
[("a",True),("c",True)]
[("b",False),("c",False)]
[("b",False),("c",True)]
[("b",True),("c",False)]
[("b",True),("c",True)]
[("a",False),("b",False),("c",False)]
[("a",False),("b",False),("c",True)]
[("a",False),("b",True),("c",False)]
[("a",False),("b",True),("c",True)]
[("a",True),("b",False),("c",False)]
[("a",True),("b",False),("c",True)]
[("a",True),("b",True),("c",False)]
[("a",True),("b",True),("c",True)]
答案 1 :(得分:1)
solution :: [a] -> [b] -> [[(a, b)]]
solution variables values = do
as <- subsequences variables
bs <- forM as $ const values
zip as bs
并证明它有效:
Data.List Control.Monad Prelude> :{
Data.List Control.Monad Prelude| let solution :: [a] -> [b] -> [[(a, b)]]
Data.List Control.Monad Prelude| solution variables values = do
Data.List Control.Monad Prelude| as <- subsequences variables
Data.List Control.Monad Prelude| bs <- forM as $ const values
Data.List Control.Monad Prelude| return $ zip as bs
Data.List Control.Monad Prelude| :}
Data.List Control.Monad Prelude> solution [ "a", "b", "c" ] [ False, True ]
[[],[("a",False)],[("a",True)],[("b",False)],[("b",True)],[("a",False),("b",False)],[("a",False),("b",True)],[("a",True),("b",False)],[("a",True),("b",True)],[("c",False)],[("c",True)],[("a",False),("c",False)],[("a",False),("c",True)],[("a",True),("c",False)],[("a",True),("c",True)],[("b",False),("c",False)],[("b",False),("c",True)],[("b",True),("c",False)],[("b",True),("c",True)],[("a",False),("b",False),("c",False)],[("a",False),("b",False),("c",True)],[("a",False),("b",True),("c",False)],[("a",False),("b",True),("c",True)],[("a",True),("b",False),("c",False)],[("a",True),("b",False),("c",True)],[("a",True),("b",True),("c",False)],[("a",True),("b",True),("c",True)]]
Data.List Control.Monad Prelude> forM_ it print
[]
[("a",False)]
[("a",True)]
[("b",False)]
[("b",True)]
[("a",False),("b",False)]
[("a",False),("b",True)]
[("a",True),("b",False)]
[("a",True),("b",True)]
[("c",False)]
[("c",True)]
[("a",False),("c",False)]
[("a",False),("c",True)]
[("a",True),("c",False)]
[("a",True),("c",True)]
[("b",False),("c",False)]
[("b",False),("c",True)]
[("b",True),("c",False)]
[("b",True),("c",True)]
[("a",False),("b",False),("c",False)]
[("a",False),("b",False),("c",True)]
[("a",False),("b",True),("c",False)]
[("a",False),("b",True),("c",True)]
[("a",True),("b",False),("c",False)]
[("a",True),("b",False),("c",True)]
[("a",True),("b",True),("c",False)]
[("a",True),("b",True),("c",True)]
答案 2 :(得分:0)
生成给定列表的所有子序列(不考虑性能)的简单解决方案是:
subs :: [a] -> [[a]]
subs [] = [[]]
subs (x:xs) = subs xs ++ map (x:) (subs xs)
答案 3 :(得分:0)
实际上这里没有必要使用monad。以下可能有点令人生畏,但我会在事后解释。注意:映射和折叠有助于编译器更快地编写代码。
solution :: [a] -> [b] -> [[(a, b)]]
solution variables values = foldr (<*>) [[]]
$ map (\variable -> id : map (\value -> (:) (variable, value) ) values)
$ variables
需要Control.Applicative
。
我们的想法是选择子序列并将所有可能的值分配为单个进程。函数(\value -> (:) (variable, value) ) :: b -> [(a,b)]->[(a,b)]
接受一个值,与变量成对,并生成一个函数,将该对附加到变量值对列表。
通过在所有值列表上进行映射,我们得到一个函数列表map (\value -> (:) (variable, value) ) values :: [[(a,b)]->[(a,b)]]
。外部列表括号用于非确定性,而内部用于绑定列表。
我们添加了另一个选项:不分配值。这是由id :: [(a,b)]->[(a,b)]
完成的,它被添加到可能性列表中。
下一个lambda-abstraction-and-map构造考虑了不同的变量:我们想要列出每个变量的可能变化。
map (\variable -> (id : map (\value -> (:) (variable, value) ) values)) variables
具有类型[[[(a,b)]->[(a,b)]]]
,其中最外面的列表用于要绑定的变量,非确定性的中间层和已绑定的变量的内部列表。
然后最后来了:折叠!折叠在最外面的列表层上工作(每个变量做一些事情),这个列表级别消失。 (<*>)
结合了所有非确定性,它是之前列表的中间层,是结果的外层。内层不受影响。折叠的起始值为[[]]::[[(a,b)]]
。
如果你习惯了Alternative
界面的非确定性,你可能更喜欢
solution :: Alternative f => [a] -> f b -> f[(a, b)]
solution variables values = foldr (<*>) (pure [])
$ map (\variable -> pure id <|> pure (\value -> (:) (variable, value)) <*> values)
$ variables
因为现在列表操作(:)
和map
用于变量列表,而有关非确定性的所有内容都由应用/替代接口处理。