【发布时间】:2011-03-20 09:09:17
【问题描述】:
我是 F# 的新手,正在寻找一个采用 N*indexes 和一个序列并给我 N 个元素的函数。如果我有 N 个索引,它应该等于 concat Seq.nth index0, Seq.nth index1 .. Seq.nth indexN 但它应该只扫描序列中的 indexN 个元素 (O(N)) 而不是 index0+index1+.. .+indexN (O(N^2)).
总而言之,我正在寻找类似的东西:
//For performance, the index-list should be ordered on input, be padding between elements instead of indexes or be ordered when entering the function
seq {10 .. 20} |> Seq.takeIndexes [0;5;10]
Result: 10,15,20
我可以通过使用 seq { yield... } 来做到这一点,并有一个索引计数器在应该传递某些元素时进行标记,但如果 F# 提供了一个很好的标准方式,我宁愿使用它。
谢谢:)...
补充:我做了以下。它有效,但不漂亮。欢迎提出建议
let seqTakeIndexes (indexes : int list) (xs : seq<int>) =
seq {
//Assume indexes is sorted
let e = xs.GetEnumerator()
let i = ref indexes
let curr = ref 0
while e.MoveNext() && not (!i).IsEmpty do
if !curr = List.head !i then
i := (!i).Tail
yield e.Current
curr := !curr + 1
}
【问题讨论】:
-
您的索引是否有序(即从最小到最大或相反)?
-
只是想知道,但是您正在编写什么样的程序需要对您的序列进行索引访问?
-
Pavel:我们可以说它们是有序的。朱丽叶:实际上,我已经解决了欧拉计划问题 40,并且可以通过纯数学来解决。但我想让我的功能解决方案看起来更好:)
-
对于它的价值,
seq并不容易分解,您有时需要使用命令式代码来处理Seq模块不能很好地处理的情况。从使用您的代码的客户的角度来看,您所拥有的已经是一个“纯”功能,并且可以满足您的特定需求。