如何计算未知大小的列表的连续元素之间的差异,从功能上? [英] How do you compute the difference between successive elements of a list of unknown size, functionally?

查看:149
本文介绍了如何计算未知大小的列表的连续元素之间的差异,从功能上?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在纯函数式编程语言(如Haskell)中,或者只使用函数式方法(例如clojure);假设你有一个list / seq / enumerable(未知大小)的整数,并且你想生成一个包含连续项之间的差异的新列表/ seq / enumerable,你会怎么做?

In a programming language that is purely functional (like Haskell) or where you are only using it in a functional way (eg clojure); suppose you have a list/seq/enumerable (of unknown size) of integers and you want to produce a new list/seq/enumerable that contains the differences between successive items, how would you do it?

我之前在C#中做的是折叠列表,并保持一个状态对象作为聚合值,记录上一个项目,以便你可以从当前项目做一个差异。结果列表还必须进入状态对象(这是未知大小列表的问题)

What I did previously in C# was to fold over the list and keep a state object as the aggregating value which recorded the 'previous' item so that you could do a diff on it from the current item. The the result list also had to go into the state object (which is a problem for a list of unknown size)

做这种事情的一般方法是什么功能上

What is the general approach for doing this kind of thing functionally?

推荐答案

在Haskell中,你可能只是使用一些更高阶函数 zipWith 。所以你可以这样做:

In Haskell you would probably just use some higher order function like zipWith. So you could do something like this:

diff [] = []
diff ls = zipWith (-) (tail ls) ls

注意我是如何处理 [] case分开 - 如果你传递一个空列表到 tail 你会得到一个运行时错误,和Haskellers真的,真的 hate运行时错误。但是,在我的函数中,我保证 ls 不为空,因此使用 tail 是安全的。 (为了参考, tail 只返回除列表第一项之外的所有项,它与Scheme中的 cdr 相同。 )

Note how I handled the [] case separately--if you pass an empty list to tail you get a runtime error, and Haskellers really, really hate runtime errors. However, in my function, I'm guaranteed the ls is not empty, so using tail is safe. (For reference, tail just returns everything except the first item of the list. It's the same as cdr in Scheme.)

这只是使用列表及其尾部,并使用( - )函数组合所有项目。

This just takes the list and its tail and combine all of the items using the (-) function.

给出一个列表 [1,2,3,4] ,将会是这样:

Given a list [1,2,3,4], this would go something like this:

zipWith (-) [2,3,4] [1,2,3,4]
[2-1, 3-2, 4-3]
[1,1,1]

是一个常见的模式:你可以通过巧妙地使用标准的高阶函数来计算出令人惊讶的许多东西。你也不怕传递一个列表和它自己的尾部到一个函数 - 没有突变,搞乱你的编译器通常是非常聪明的优化这样的代码。

This is a common pattern: you can compute surprisingly many things by cleverly using standard higher-order functions. You are also not afraid of passing in a list and its own tail to a function--there is no mutation to mess you up and the compiler is often very clever about optimizing code like this.

同时,如果你喜欢列表推导,并且不介意启用 ParallelListComp 扩展,你可以写 zipWith ls)ls 像这样:

Coincidentally, if you like list comprehensions and don't mind enabling the ParallelListComp extension, you could write zipWith (-) (tail ls) ls like this:

[b - a | a <- ls | b <- tail ls]

这篇关于如何计算未知大小的列表的连续元素之间的差异,从功能上?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆