首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >递归地将非连续列表排序为连续列表列表

递归地将非连续列表排序为连续列表列表
EN

Stack Overflow用户
提问于 2011-02-18 08:08:29
回答 12查看 789关注 0票数 6

最近我一直在尝试学习一些函数式编程(使用Haskell和Erlang),当人们能够以递归方式思考并了解工具时,我总是对他们能想出简洁的解决方案感到惊讶。

我想要一个函数来将排序的、唯一的、不连续的整数列表转换为连续列表的列表,即:

代码语言:javascript
运行
复制
[1,2,3,6,7,8,10,11]

至:

代码语言:javascript
运行
复制
[[1,2,3], [6,7,8], [10,11]

这是我在Haskell中能想到的最好的方法(两个函数):

代码语言:javascript
运行
复制
make_ranges :: [[Int]] -> [Int] -> [[Int]]
make_ranges ranges [] = ranges
make_ranges [] (x:xs)
    | null xs = [[x]]
    | otherwise = make_ranges [[x]] xs
make_ranges ranges (x:xs)
    | (last (last ranges)) + 1 == x =
        make_ranges ((init ranges) ++ [(last ranges ++ [x])]) xs
    | otherwise = make_ranges (ranges ++ [[x]]) xs

rangify :: [Int] -> [[Int]]
rangify lst = make_ranges [] lst    

这可能有点主观,但我希望看到一个更好、更优雅的Erlang或Haskell解决方案(其他函数式语言也可以,但我可能不理解它)。否则,我只想修复我糟糕的初学者的Haskell风格!

EN

Stack Overflow用户

发布于 2011-02-18 08:59:38

代码语言:javascript
运行
复制
import Data.List (groupBy)

ranges xs = (map.map) snd 
          . groupBy (const fst) 
          . zip (True : zipWith ((==) . succ) xs (tail xs))
          $ xs

至于如何想出这样的东西:我从zipWith f xs (tail xs)开始,当你想对列表中连续的元素做一些事情时,这是一个常见的习惯用法。与此类似的是,zip使用有关列表的信息ping列表,然后对其执行操作(groupBy)。剩下的就是管道了。

然后,当然,您可以通过@pl提供它并获取:

代码语言:javascript
运行
复制
import Data.List (groupBy)
import Control.Monad (ap)
import Control.Monad.Instances()

ranges = (((map.map) snd) 
           . groupBy (const fst)) 
         .) =<< zip 
         . (True:) 
         . ((zipWith ((==) . succ)) `ap` tail)

,根据我的权威定义,这是由于Mondad ((->) a)造成的邪恶。甚至两次。数据流过于曲折,无法以任何合理的方式进行布局。zipaptail是阿兹特克人的神,阿兹特克人的神是不能乱来的。

票数 4
EN
查看全部 12 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5036284

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档