我有一个x元素列表,我想从中获得所有可能的唯一n元组。
所以我基本上正在寻找
的实现nub . map (take n) . permutations
不会不必要地创建重复项。
对我来说,这看起来像是一个很有可能在某处被定义的函数。
是这样的吗?
答案 0 :(得分:1)
你的意思是这样吗?
import Data.List (permutations)
choose n list = concatMap permutations $ choose' list [] where
choose' [] r = if length r == n then [r] else []
choose' (x:xs) r | length r == n = [r]
| otherwise = choose' xs (x:r)
++ choose' xs r
输出:
*Main> choose 2 [0..5]
[[1,0],[0,1],[2,0],[0,2],[3,0],[0,3],[4,0],[0,4],[5,0],[0,5],[2,1]
,[1,2],[3,1],[1,3],[4,1],[1,4],[5,1],[1,5],[3,2],[2,3],[4,2],[2,4]
,[5,2],[2,5],[4,3],[3,4],[5,3],[3,5],[5,4],[4,5]]
答案 1 :(得分:0)
Hayoo对查找功能很有帮助。有了这个query,我找到了permutation包,看起来它可能会做你想要的,虽然我没有详细检查实现。
但是使用Stack Overflow中讨论的解决方案之一可能更简单。 search发现了一些相关帖子。您可以查看Data.List中permutations
函数的discussion实现,并对其进行修改以满足您的需求。
答案 2 :(得分:0)
既然你已经要求了元组,那么这是一个利用list是一个应用函子的事实的解决方案:
Prelude> let list = [0..4]
Prelude> import Control.Applicative
Prelude Control.Applicative> (,) <$> list <*> list
[(0,0),(0,1),(0,2),(0,3),(0,4),(1,0),(1,1),(1,2),...
Prelude Control.Applicative> (,,) <$> list <*> list <*> list
[(0,0,0),(0,0,1),(0,0,2),(0,0,3),(0,0,4),(0,1,0),(0,1,1),...
然而,由于不同类型的元组根据定义是不同的类型,因此不可能编写一个通用函数,它将根据某些n
参数生成不同元素的结果。
虽然我必须注意,这可以通过使用一些高级类型级编程技术来解决,方法是为类型级自然引入一个类型级和实例,代表你想要支持的元组的元素,但我相信这会是一个矫枉过正的人。此外,利用type-naturals也是多余的,因为所有必需的信息都可以从结果类型中确定,因此一个简单的类型类和你想要支持的所有元组的实例就足够了。
答案 3 :(得分:0)
您可以使用Math.Combinatorics.Multiset
(cabal install multiset-comb
),即使输入列表中有重复项,也可以避免输出列表中的重复:
import Math.Combinatorics.Multiset (fromList, kSubsets, permutations)
permute :: Ord a => Int -> [a] -> [[a]]
permute n = concatMap permutations . kSubsets n . fromList
main = print $ permute 2 [1, 1, 2, 3]
产地:
[[2,3],[3,2],[1,3],[3,1],[1,2],[2,1],[1,1]]