时间:2010-07-23 23:31:53

标签: f# sequence indexing

4 个答案:

答案 0 :(得分:7)

答案 1 :(得分:2)

答案 2 :(得分:1)

答案 3 :(得分:0)

是否存在问题,返回的结果是否已排序? 该算法将在输入序列上线性工作。只需要对索引进行排序。如果序列很大,但索引不是那么多 - 它会很快。 复杂性是:N - > Max(指数),M - >指数计数:最坏情况下为O(N + MlogM)。

let seqTakeIndices indexes = 
    let rec gather prev idxs xs =
        match idxs with
        | [] -> Seq.empty
        | n::ns ->  seq { let left = xs |> Seq.skip (n - prev)
                          yield left |> Seq.head
                          yield! gather n ns left }
    indexes |> List.sort |> gather 0

这是一个List.fold变体,但读取起来比较复杂。我更喜欢第一个:

let seqTakeIndices indices xs = 
    let gather (prev, xs, res) n =
        let left = xs |> Seq.skip (n - prev)
        n, left, (Seq.head left)::res
    let _, _, res = indices |> List.sort |> List.fold gather (0, xs, [])
    res

附加:仍然比你的变种慢,但比我的旧变种要快很多。因为没有使用Seq.skip来创建新的枚举器并且正在减慢很多事情。

let seqTakeIndices indices (xs : seq<_>) = 
    let enum = xs.GetEnumerator()
    enum.MoveNext() |> ignore
    let rec gather prev idxs =  
        match idxs with
        | [] -> Seq.empty
        | n::ns -> seq { if [1..n-prev] |> List.forall (fun _ -> enum.MoveNext()) then 
                            yield enum.Current
                            yield! gather n ns }
    indices |> List.sort |> gather 0