简体   繁体   English

Haskell:从x元素列表中创建唯一的n元组

[英]Haskell: Create unique n-tuples from a list of x elements

I have a list of x elements from which I would like to have all possible unique n-tuples. 我有一个x元素列表,我希望从中获得所有可能的唯一n元组。

So I basically am looking for an implementation of 所以我基本上是在寻找实现

nub . map (take n) . permutations

that doesn't unnecessarily create the duplicates. 不必创建重复项。

For me, this looks like a function that has a good chance of being defined already somewhere. 对我来说,这看起来像一个很可能已经在某个地方定义的函数。

Is this the case? 是这样吗

Do you mean something like this? 你的意思是这样吗?

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

Output: 输出:

*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]]

Hayoo is very helpful for finding functions. Hayoo对于查找功能非常有帮助。 With this query , I found the permutation package, which seems it might do what you want, although I haven't examined the implementation in detail. 通过这个查询 ,我找到了置换包,尽管我没有详细研究实现,但它似乎可以满足您的要求。

But it might be simpler to use one of the solutions discussed here on Stack Overflow. 但是,使用此处在堆栈溢出中讨论的解决方案之一可能会更简单。 A search turned up some relevant posts. 搜索后发现了一些相关的帖子。 You might look at this discussion of the implementation of the permutations function in Data.List, and modify it to meet your needs. 您可能会看一下有关 Data.List中permutations功能实现的讨论 ,并对其进行修改以满足您的需求。

Since you've asked for tuples, here is a solution exploiting the fact that list is an applicative functor: 既然您已请求元组,那么以下是利用列表是应用函子的事实的解决方案:

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),...

However, since tuples of different arities are different types by definition, it's impossible to write a universal function which will produce results of different arities based on some n parameter. 但是,由于定义不同类型的元组的类型不同,因此不可能编写一个通用函数,该函数将基于某个n参数产生不同类型的结果。

Although I must note that this could be solved using some advanced type-level programming techniques by introducing a type-class and instances for type-level naturals representing the arities of tuples you wanted to support, but I'm sure this would be an overkill. 虽然我必须指出,可以通过使用一些高级类型级编程技术来解决此问题,方法是为代表您要支持的元组的元组引入类型级自然类型的类型类和实例,但是我敢肯定这会过分。 Besides, utilizing type-naturals would also be redundant, since all the required information could be determined from the result type, so a simple type class and instances for all tuples you wanted to support would be enough. 此外,利用自然类型也将是多余的,因为所有必需的信息都可以从结果类型中确定,因此,一个简单的类型类和您要支持的所有元组的实例就足够了。

You can use Math.Combinatorics.Multiset ( cabal install multiset-comb ), which will avoid duplicates in the output list even if there are duplicates in the input list: 您可以使用Math.Combinatorics.Multisetcabal 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]

Produces: 生产:

[[2,3],[3,2],[1,3],[3,1],[1,2],[2,1],[1,1]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM