首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么F#的Seq.windowed会返回数组的序号

为什么F#的Seq.windowed会返回数组的序号
EN

Stack Overflow用户
提问于 2013-07-10 14:37:26
回答 3查看 1.2K关注 0票数 10

F#中的Seq.windowed返回一个序列,其中每个窗口都是一个数组。为什么每个窗口都作为数组(一个非常具体的类型)返回,而不是作为另一个序列或IList<'T>返回?例如,如果目的是传达窗口的项可以被随机访问,那么IList<'T>就足够了,但是数组说明了两件事:元素是可变的和随机访问的。如果您可以合理选择阵列,那么windowedSeq.groupBy有什么不同呢?为什么后者(或类似的运算符)不也将组的成员作为数组返回?

我想知道这是简单的设计疏忽,还是有更深层次的合同原因?

EN

回答 3

Stack Overflow用户

发布于 2013-07-10 22:17:31

我不知道这背后的设计原则是什么。我认为这可能只是实现的一个偶然方面- Seq.windowed可以通过将项存储在数组中来非常容易地实现,而Seq.groupBy可能需要使用一些更复杂的结构。

一般来说,我认为,如果使用数组是自然有效的实现,则F# API要么使用'T[],要么当数据源可能是无限的、惰性的,或者当实现必须显式地将数据转换为数组时返回seq<'T> (然后这可以留给调用者)。

对于Seq.windowed,我认为数组很有意义,因为您知道数组的长度,因此很可能会使用索引。例如,假设prices是一系列日期-价格元组(seq<DateTime * float>),您可以这样写:

代码语言:javascript
复制
prices
|> Seq.windowed 5
|> Seq.map (fun win -> fst (win.[2]), Seq.averageBy snd win)

该示例计算浮动平均值,并使用索引来获取中间的日期。

总而言之,我对设计原理没有很好的解释,但我对所做的选择相当满意-它们似乎与函数的常见用例工作得非常好。

票数 7
EN

Stack Overflow用户

发布于 2013-11-07 11:25:23

有几个想法。

首先,要知道在其当前版本中,Seq.windowedSeq.groupBy在其实现中都使用了非惰性集合。windowed使用数组并返回数组。groupBy构建了一个Dictionary<'tkey, ResizeArray<'tvalue>>,但对此保密,并以seq而不是ResizeArray的形式返回组值。

groupBy返回ResizeArrays不适用于其他任何内容,因此显然需要隐藏。另一种选择是返回数据的ToArray()。这将需要创建数据的另一个副本,这是一个缺点。而且没有太多的好处,因为你不知道你的组会有多大,所以你不会期望进行随机访问或任何其他特殊的数组支持的东西。因此,简单地包装在seq中似乎是一个很好的选择。

对于windowed来说,这是一个不同的故事。在本例中,您希望返回一个数组。为什么?因为您已经知道该数组将有多大,所以您可以安全地进行随机访问,或者更好的是,进行模式匹配。这是一个很大的好处。然而,缺点仍然存在-数据需要重新复制到每个窗口的新分配的数组中。

代码语言:javascript
复制
seq{1 .. 100} |> Seq.windowed 3 |> Seq.map (fun [|x; _; y|] -> x + y)

仍然有一个悬而未决的问题-“但是我们不能通过在内部只使用真正的惰性seq来避免数组分配/复制的负面影响吗?这样做不是更符合‘seq的精神’吗?”这可能有点棘手(需要一些花哨的枚举数克隆?),但可以肯定的是,可能需要一些仔细的编码。不过,这也有一个很大的缺点。您需要在内存中缓存整个未假脱机的seq才能使其工作,这在某种程度上否定了懒惰做事情的整个目标。与列表或数组不同,多次枚举seq并不能保证产生相同的结果(例如,返回随机数的seq ),因此需要将返回的这些seq窗口的备份数据缓存到某个地方。当该窗口最终被访问时,您不能只是点击并重新枚举原始源seq -您可能会得到不同的数据,或者seq可能在不同的位置结束。这指出了在Seq.windowed中使用数组的另一个好处--只有windowSize元素需要一次保存在内存中。

票数 6
EN

Stack Overflow用户

发布于 2013-11-05 22:13:03

这当然是纯粹的猜测。我认为这与两个函数的实现方式有关。

如前所述,在Seq.groupBy中,组的长度是可变的,而在Seq.windowed中,组的大小是固定的。

因此,在Seq.windowed的实现中,使用固定大小的数组更有意义,而不是Seq.groupBy中使用的Generic.List,F#中的btw称为ResizeArray

现在,尽管Array是可变的,但在F#代码和库中被广泛使用,F#为创建、初始化和操作数组提供语法支持,而ResizeArray在F#代码中使用不是很广泛,该语言除了类型别名之外没有提供语法支持,所以我认为这就是他们决定将其公开为Seq的原因。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17563956

复制
相关文章

相似问题

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