我有很多名单。简称[[1,2],[3,4]]
。
我需要生成每个元素的所有符号变化。因此,对于简短的例子,结果将是
[[1,2],[3,4],[-1,2],[1,-2],[-1,-2],[-3,4],[3,-4],[-3,-4]]
是否有包执行此类操作?否则我可以使用什么算法? (我承认我没有想过很多......)。
这可以提供帮助,我的所有列表都有相同的长度。
x = [[2*i,2*j] | i <- [1, -1], j <- [-1,1]]
x
[[2,-2],[2,2],[-2,-2],[-2,2]]
答案 0 :(得分:6)
问题可以分解为两个步骤:
对于1.您可以编写一个简单的递归函数,首先处理列表的尾部,然后对于每个结果组合,它为这两个符号生成两个版本。
signs :: [Int] -> [[Int]]
signs [] = [[]]
signs (x : xs)
= let ps = signs xs
in map (x :) ps ++ map ((-x) :) ps
对于2.只需将signs
函数映射到输入上,然后将它们连接起来。这就是concatMap
函数的作用:
signsAll :: [[Int]] -> [[Int]]
signsAll = concatMap signs
答案 1 :(得分:4)
我试图在这里使用一个应用程序,因为它看起来像你几乎在那里
[id,negate] <*> [3,4]
但事实证明我需要sequence
和map
,在这种情况下,可以合并为traverse
:
traverse (\x->[x,-x]) [3,4]
[[3,4],[3,-4],[-3,4],[-3,-4]]
正如其他人所提到的,现在你的功能需要concatMap
:
concatMap (traverse (\x->[x,-x])) [[3,4],[1,2]]
[[3,4],[3,-4],[-3,4],[-3,-4],[1,2],[1,-2],[-1,2],[-1,-2]]