List 组合需要一段时间、一段时间

List 组合需要一段时间、一段时间,list,f#,List,F#,在F#中,我发现当我想使用takeWhile时,我通常还想使用skipWhile,也就是说,使用满足谓词的列表前缀,并记住列表的其余部分以供后续处理。我不认为有一个标准的库函数可以同时实现这两个功能,但我可以很容易地编写一个 我的问题是,这种组合应该叫什么?很明显,它应该有一个标准名称;它是什么?到目前为止,我想到的最好的方法是split,它似乎与splitAt一致。slice可以捕获连续范围的意图: List.slice skipPredicate takePredicate span是我见

在F#中,我发现当我想使用
takeWhile
时,我通常还想使用
skipWhile
,也就是说,使用满足谓词的列表前缀,并记住列表的其余部分以供后续处理。我不认为有一个标准的库函数可以同时实现这两个功能,但我可以很容易地编写一个


我的问题是,这种组合应该叫什么?很明显,它应该有一个标准名称;它是什么?到目前为止,我想到的最好的方法是
split
,它似乎与
splitAt
一致。slice
可以捕获连续范围的意图:

List.slice skipPredicate takePredicate

span
是我见过的这个函数的另一个名称。例如,

你问题的这一部分对我来说很突出(强调我的问题):

获取满足谓词的列表前缀,并记住列表的其余部分,以便后续处理

我猜您希望递归列表的其余部分,然后再次应用此拆分函数。这是我以前几次想做的。最初,我编写了我认为您正在描述的函数,但在仔细考虑之后,我意识到可能有一种更通用的方法来考虑它,并完全避免递归,这通常会使代码更简单。这就是我提出的函数

module List =
    let groupAdjacentBy f xs =
        let mutable prevKey, i = None, 0
        xs
        |> List.groupBy (fun x ->
            let key = f x
            if prevKey <> Some key then
                i <- i + 1
                prevKey <- Some key
            (i, key))
        |> List.map (fun ((_, k), v) -> (k, v))

let even x = x % 2 = 0
List.groupAdjacentBy even [1; 3; 2; 5; 4; 6]
// [(false, [1; 3]); (true, [2]); (false, [5]); (true, [4; 6])]
模块列表=
设groupappendentbyfxs=
设可变prevKey,i=None,0
xs
|>List.groupBy(乐趣x->
设key=fx
如果你需要一些钥匙,那么
i(k,v))
设偶数x=x%2=0
List.groupappendentby偶数[1;3;2;5;4;6]
//[(假,[1;3]);(真,[2]);(假,[5]);(真,[4;6])]
我发现这个名字更容易命名,也更有用。也许它能解决你目前的问题。如果您不需要组密钥,则可以通过添加
|>List.map snd
来删除它们


虽然我通常避免变异,但在这里使用它可以让我使用
List.groupBy
并避免编写更多的代码。

split
听起来不错,或者
splitBy
怎么样?我认为
List.partition
对您没有帮助?它还基于谓词将列表分成两半,但在整个列表中都是如此,不仅是第一个不匹配的元素。我也同意
split
对于使用谓词的函数最有意义,因为它与
filter
find
exists等函数的使用是并行的。但是如果你想使用“split+一些介词”,我建议使用
splitWith
,而不是
splitBy
。其他在名称中使用“by”的函数(
maxBy
sortBy
averageBy
,等等)期望使用一个投影函数作为其第一个参数,而使用“with”(
compareWith
sortWith
)的函数则期望使用我称之为“helper”的函数(做出决策的函数)。所以“by”比“with”更合适,但没有后缀最合适。是不是
SkipAndTake
太多了?或者可能是
TakeAfter
?一两个输入和期望输出的具体例子就值千言万语了:)