【问题标题】:Haskell takeWhile but for list, not its elementsHaskell takeWhile 但对于列表,而不是它的元素
【发布时间】:2015-10-04 00:22:24
【问题描述】:

我有一个无限列表,我将它连接到一个字符串。

foldl1 (++) $ map show [1..]

我想要的是当这个字符串的长度达到十个或更多字符时将其切断。

但是,takeWhile 对列表的各个元素进行操作。当列表超过十个字符时,我可以使用一个函数来切断列表吗?

在这种情况下,我希望函数输出“123456789”,忽略 10,因为越过会导致长度过大。

编辑:这是我的实际代码。这就是我所描述的。

succProd x = last. takeWhile ((<10).length) . scanl1 (++) $ map (show.(x*)) [1..]

谢谢!

【问题讨论】:

  • 无限列表实际上比[1..]复杂一点。这仅仅是一个例子。 :)
  • 编辑您的问题并添加真实示例。
  • 当然。我认为这更清楚,我已经得到了我需要的答案,但是好吧。
  • @DanMaheshwari 你能改写你的问题吗?它没有说明您希望在 构建 列表时执行此操作 - 我以为您只是在这里谈论 take 一段时间。

标签: haskell


【解决方案1】:

使用scanl 而不是foldl 来获取所有中间结果的列表,并获取您满意的最后一个:

last . takeWhile ((< 10) . length) . scanl1 (++) $ map show [1..]
"123456789"

【讨论】:

  • 这会重新计算每个中间列表的长度。如果性能是一个问题,您可以执行takeWhile ((&lt; Sum n) . fst) . scanl1 (&lt;&gt;) . map (Sum . length &amp;&amp;&amp; id) 之类的操作。
【解决方案2】:

使用inits 从列表的开头生成子字符串,在未传达条件时将其删除,

import Data.List
head . dropWhile ((<10-1) . length ) $ inits $ concatMap show [1..]

last . takeWhile ((<10) . length ) $ inits $ concatMap show [1..]

【讨论】:

  • 这只是take 9 . concatMap show 的另一种写法。计算inits 的每个元素并不有趣,因为您知道每次迭代它的大小都会增加1。这个问题的问题是如何完全“丢弃”最后一个会导致结果太大的元素。即,如果列表中还有一个字符的“空间”并且下一个数字是 10,则不应添加更多字符,因为 10 需要两个字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
  • 1970-01-01
  • 2023-03-31
相关资源
最近更新 更多