一个列表的子集,从一个元素开始。

3
我需要获取F#列表中某个元素第一次出现后的子集。我使用了一个简单的递归程序来实现:
// Returns a subset of a list from the first occurrence of a given item
// e.g. ignoreUpTo "B" ["A";"B";"C";"D"] yields ["C"; "D"]

let rec ignoreUpTo item l  = 
  match l with
  | hd::tl -> if hd = item then tl else ignoreUpTo item tl 
  | _ -> []

这对我的需求来说有效,但我想知道是否有更好的方法使用F#语言中现有的List函数来完成此操作。

如果列表中不包含该元素,您计划返回什么?一个空列表吗?还是该函数应该返回包装在选项中的列表? - Kevin W.
在我的情况下,空列表是可以的,因为这正是我明确检查的内容。 - Russell
2个回答

4
如果您正在使用F# 4,现在有一个名为List.skipWhile的函数;在F# 4之前,skipWhile函数只能用于seq。因此,您可以编写以下代码:
let ignoreUpTo item l =
  l
  |> List.skipWhile ((<>) item)
  |> List.skip 1  // Because otherwise you'll get ["B"; "C"; "D"]

如果您使用的是 F# 3.1 或更早版本,您需要先将列表转换为 seq:
let ignoreUpTo item l =
  l
  |> List.toSeq
  |> Seq.skipWhile ((<>) item)
  |> Seq.skip 1  // Because otherwise you'll get ["B"; "C"; "D"]
  |> Seq.toList  // Optional, if you can get by with a seq instead of a list

请注意,我只是写了这些代码,但还没有测试过。特别是,当传递一个空列表时,我不知道 List.skip 1 会发生什么。@hvester 在他的解决方案中提出的 match 建议可能是值得尝试的好方法。 - rmunn
哎呀,我不小心写成了 takeWhile 而不是 skipWhile。在我纠正之前,那两个点赞了我的错误解决方案的人居然没有注意到... 唉,唉。 :-) - rmunn

3
你可以使用List.skipWhile来实现它。我假设你想在列表l中没有元素等于item时返回空列表。
let ignoreUpTo item l =
    match List.skipWhile ((<>) item) l with
    | [] -> []
    | x :: xs -> xs 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接