获取序列的每个第n个元素

Ale*_*erg 7 f#

我正在寻找一种方法来创建一个由另一个序列的每个第n个元素组成的序列,但似乎没有找到一种方法以优雅的方式做到这一点.我当然可以破解某些东西,但我想知道是否有一个我没有看到的库函数.

名称以-i结尾的序列函数似乎非常适合于确定元素何时是第n个或第n个(第n个的多个),但我只能看到,iteri并且mapi没有一个真正适合于任务.

例:

let someseq = [1;2;3;4;5;6]
let partial = Seq.magicfunction 3 someseq
Run Code Online (Sandbox Code Playgroud)

partial应该是[3;6].那里有什么类似的东西吗?

编辑:

如果我不是那么雄心勃勃并且允许n不变/已知,那么我刚刚发现以下内容应该有效:

let rec thirds lst =
    match lst with
    | _::_::x::t -> x::thirds t // corrected after Tomas' comment
    | _ -> []
Run Code Online (Sandbox Code Playgroud)

有没有办法写这个更短?

Ste*_*sen 9

Seq.choose在这些情况下很好地工作,因为它允许你filtermapilambda中完成工作.

let everyNth n elements =
    elements
    |> Seq.mapi (fun i e -> if i % n = n - 1 then Some(e) else None)
    |> Seq.choose id
Run Code Online (Sandbox Code Playgroud)

类似.


Tom*_*cek 8

您可以通过mapi与其他功能合成来获得该行为:

let everyNth n seq = 
  seq |> Seq.mapi (fun i el -> el, i)              // Add index to element
      |> Seq.filter (fun (el, i) -> i % n = n - 1) // Take every nth element
      |> Seq.map fst                               // Drop index from the result
Run Code Online (Sandbox Code Playgroud)

使用选项和chooseAnnon建议的解决方案只使用两个函数,但第一个函数的主体稍微复杂一些(但原理基本相同).

IEnumerator直接使用该对象的更高效版本并不难写:

let everyNth n (input:seq<_>) = 
  seq { use en = input.GetEnumerator()
        // Call MoveNext at most 'n' times (or return false earlier)
        let rec nextN n = 
          if n = 0 then true
          else en.MoveNext() && (nextN (n - 1)) 
        // While we can move n elements forward...
        while nextN n do
          // Retrun each nth element
          yield en.Current }
Run Code Online (Sandbox Code Playgroud)

编辑:该片段也可在此处获取:http://fssnip.net/1R