list - Haskell 组列表直到组满足谓词

标签 list haskell

如何对列表进行分组,以便一旦给定谓词不再成立,每个组就会“关闭”。类似的东西

groupWhile :: [Int] -> ([Int]->Bool) -> [[Int]]

这样

groupWhile [1,2,3,5,7,1,3,5,7] (\xs ->  (<=4) $ length $ filter odd xs) 
     = [[1,2,3,5,7],[1,3,5,7]]

我需要这个来玩纸牌游戏,我想将事件分组为几轮,这样每轮都有四张牌。然而,并非所有事件都是“卡片”事件(上例中的偶数)。

Data.List 和 Data.List.Split 函数似乎都没有做这样的事情。谓词似乎总是应用于源列表元素。

最佳答案

最基本的是,我们有

   groupWhile as pred = collect [] as where
     collect acc []     = reverse acc
     collect acc (x:xs) =
       let acc'  = x:acc
           racc' = reverse acc'
       in if pred racc'
          then racc' : collect [] xs
          else collect acc' xs

虽然这会造成很多逆转。我们可以使用 Data.List 中的两个函数更直接地计算它。

import Data.List (inits, tails)

-- forall finite (ls :: [a]) . length (inits ls) == length (tails ls)

groupWhile :: [a] -> ([a] -> Bool) -> [[a]]
groupWhile as p = pop (inits as) (tails as) where
  pop [] [] = [] 
  pop (initAs:is) (tailAs:ts)
    | p initAs  = initAs : groupWhile tailAs p
    | otherwise = pop is ts

这里 inits 构建了可能的组列表,按包含顺序排序,tails 构建了“延续”,即列表的其余部分(前提是我们选择当前组)。它们是一起生成的,每当我们将一个新的成功找到的组添加到我们的结果中时,我们就会重新继续“当前延续”tailAs。否则,我们将重复 pop 函数。

关于list - Haskell 组列表直到组满足谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21101891/

相关文章:

python - 为什么嵌套循环比扁平循环执行得快得多?

python - 在不同行中打印列表中的多个项目

android - 如何使用 Switch 基于字符串对 RecyclerView 中的 CardView 进行排序?

haskell - 使用 Haskell 从麦克风捕获音频输入?

haskell - 在 Haskell 中处理签名的二进制数据而不使用 unsafeCoerce

python - 等量合并两个列表

C++ 使用 "-"操作数和 list.back()

sockets - 使用 Data.Binary 编码二进制编码的大小

haskell - 读取 haskell 中的数字列表

haskell - Haskell 中涉及列表推导式、递归和删除函数的排列