【问题标题】:Haskell: Create unique n-tuples from a list of x elementsHaskell:从 x 元素列表创建唯一的 n 元组
【发布时间】:2013-08-18 23:28:24
【问题描述】:

我有一个 x 元素列表,我希望从中获得所有可能的唯一 n 元组。

所以我基本上是在寻找一个实现

nub . map (take n) . permutations

不会不必要地创建重复项。

对我来说,这看起来像是一个很有可能已经在某个地方定义的函数。

是这样吗?

【问题讨论】:

  • 您确定nub . take n . permutations 会产生您想要的结果(无论它可能效率如何)?要么我误解了你想要什么,要么nub . take n . permutations 不会这样做。您能否提供一些您期望的输入和输出示例?
  • 也许你打算写类似nub . map (take n) . permutations $ "abcde"的东西?
  • 是的,忘记地图了,你完全正确

标签: haskell


【解决方案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]]

【讨论】:

    【解决方案2】:

    Hayo 对查找函数很有帮助。通过这个query,我找到了permutation 包,它似乎可以满足您的需求,尽管我没有详细检查实现。

    但使用 Stack Overflow 上讨论的解决方案之一可能会更简单。 search 出现了一些相关的帖子。你可以看看Data.List中permutations函数的实现这个discussion,并修改它以满足你的需要。

    【讨论】:

    • 来自 permutation 包的 Data.Choose.chooseList 似乎正是提问者正在寻找的内容。
    【解决方案3】:

    既然你已经要求元组,这里有一个利用列表是一个应用函子这一事实的解决方案:

    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 参数产生不同的元组结果。

    虽然我必须指出,这可以通过引入类型类和表示您想要支持的元组的元组的类型级自然数的实例来使用一些高级类型级编程技术来解决,但我相信这会有点矫枉过正。此外,使用自然类型也是多余的,因为所有需要的信息都可以从结果类型中确定,所以一个简单的类型类和你想要支持的所有元组的实例就足够了。

    【讨论】:

    • 我不确定元组,但您可以根据输入参数返回不同大小的列表。
    • @groovy 当然,但问题是关于元组的。
    • 可以辩论的——他举的例子是nub . map (take n) . permutations
    • 我也许可以解决这个问题:你们都是对的——问题是关于元组的。然而,由于与 Nikita 提出的关于元组案例不可能具有通用函数的相同考虑,我将我的示例粘贴到结果列表中。我的案子有明确的定义。此外,这个问题原来只是学术性质的,因为我发现对于我的用例,首先消除重复是不必要的,所以实际上,简单的理解就可以了。
    【解决方案4】:

    可以使用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]]
    

    【讨论】:

      猜你喜欢
      • 2023-03-31
      • 1970-01-01
      • 2012-01-09
      • 1970-01-01
      • 2020-06-26
      • 2022-01-18
      • 1970-01-01
      • 2022-01-18
      相关资源
      最近更新 更多