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

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

问题描述

在纯函数式编程语言中(如 Haskell)或仅以函数式方式使用它的编程语言(如 clojure);假设您有一个整数列表/序列/枚举(大小未知),并且您想生成一个包含连续项目之间差异的新列表/序列/枚举,您会怎么做?

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

注意我是如何单独处理 [] 案例的——如果你将一个空列表传递给 tail,你会得到一个运行时错误,Haskellers 真的em>,真的讨厌运行时错误.但是,在我的函数中,我保证 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 (-) (tail 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天全站免登陆