【问题标题】:haskell elegant way to filter (reduce) sequences of duplicates from infinte list of numbershaskell 优雅的方式从无限的数字列表中过滤(减少)重复序列
【发布时间】:2020-12-24 11:25:02
【问题描述】:

这是一个产生无限随机数列表的函数

import System.Random
values :: [Int]
values = map fst $ scanl (\(r, gen) _ -> randomR (1,10) gen) (randomR (1,10) (mkStdGen 1)) $ repeat ()

我想将重复元素的序列减少为一个元素,例如 [2,3,4,1,7,7,7,3,4,1,1,1,3,..] -> [2,3,4,1,7,3,4,1,3 ,..]

所以,我需要一些来自 [Int] -> [Int] 的优雅函数 "f" 来执行此操作。 此外,它必须懒惰地使用无限列表,所以如果我运行

f values

不能挂起并实时输出数据

【问题讨论】:

  • f = map head . group
  • values 的表达式可以简化为 randomRs (1,10) (mkStdGen 1)

标签: haskell filter sequence


【解决方案1】:

您可以使用group :: Eq a => [a] -> [[a]] 制作组列表。所以对于给定的样本数据,这将生成:

Prelude> import Data.List(group)
Prelude Data.List> group [2,3,4,1,7,7,7,3,4,1,1,1,3]
[[2],[3],[4],[1],[7,7,7],[3],[4],[1,1,1],[3]]

然后我们可以为每个子列表只产生带有head的第一个元素,我们知道这样的元素存在,否则它永远不会首先构造一个新组:

Prelude Data.List> map head (group [2,3,4,1,7,7,7,3,4,1,1,1,3])
[2,3,4,1,7,3,4,1,3]

这意味着您可以将f 定义为:

import Data.List(group)

f :: Eq a => [a] -> [a]
f = map head . group

这也适用于无限列表。例如,如果我们以5s 的无限列表结束列表,那么它会处理该列表直到这五个并继续寻找新值:

Prelude Data.List> map head (group (2 : 3 : 4 : 1 : 7 : 7 : 7 : 3 : 4 : 1 : 1 : 1 : 3 : repeat 5))
[2,3,4,1,7,3,4,1,3,5

或者我们可以使用Data.List.NonEmptygroup :: (Foldable f, Eq a) => f a -> [NonEmpty a]

import Data.List.NonEmpty(group)
import qualified Data.List.NonEmpty as NE

f :: Eq a => [a] -> [a]
f = map NE.head . group

【讨论】:

  • map head 相同的一般安全方法是concatMap (take 1)
  • @WillNess: 但是这里我们知道子列表不会为空,有一个group 的变体会生成NonEmptys...
  • 好吧,从技术上讲,我没有说“技术上”。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 2020-06-13
  • 2020-06-15
  • 2020-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多