将列表拆分为排序的子列表

时间:2018-12-16 16:50:36

标签: list sorting split f# subsequence

我正在尝试将具有整数的列表拆分为具有升序值的子列表。

例如:$users =User::where('role', '2')->get(); foreach($users as $user) { dump($user->information); } 应该进入[1;2;3;3;4]和列表[[1;2;3;3;4]]-> [1;2;3;2;4;3;5]

我试图通过尾递归来做到这一点,但是我不知道该怎么做。

2 个答案:

答案 0 :(得分:0)

您可以使用2个累加器。

let  splitToSorted lst =
let rec loop lst sub acc = 
    match lst with
    | [] -> (sub |> List.rev)::acc |> List.rev
    | h::t -> match sub with
              | [] -> loop t [h] acc
              | x::xs -> if (x < h)
                         then loop t (h::sub) acc
                         else loop t [x] ((sub |> List.rev)::acc)
loop lst [] []

答案 1 :(得分:0)

如果您要展示自己尝试过的内容,那么我们将在您遇到的特定问题上为您提供帮助。

此外,请尝试概括您的问题,以便找到已经提供的可能方法,例如“我有一个部分排序的列表,想通过谓词将其拆分,比较两个相邻的值”。那可能导致您找到答案,例如 F# how to Window a sequence based on predicate rather than fixed length

如果这些都不符合您的要求,请尝试一下。这是一个嵌套的递归函数,将累加器和参数组合为一个元组,累加器及其子列表在用完所有参数后需要反转。

gatsby-node.js

修改

好的,让我们退后一步。递归函数应该为tail recursive,也就是说,递归调用该函数时,您应该没有未完成的业务;它可能会使堆栈溢出。相应地,这需要一个附加的参数来累加您到目前为止计算出的中间值,通常称为累加器。

同时,累加器是查找先前值并将其与当前值进行比较的便捷位置。除了当累加器为空时-这就是为什么我们需要同时对累加器和参数进行匹配,以处理其中一种为空的特殊情况。

很容易看出如何排除谓词测试,从而产生上述版本。

let splitWhen p xs =
    let rec aux = function
    | ((y::_)::_) as yss, x::xs when p x y -> aux ([x]::yss, xs)
    | ys::yss, x::xs -> aux ((x::ys)::yss, xs)
    | [], x::xs -> aux ([[x]], xs)
    | yss, [] -> List.rev <| List.map List.rev yss
    aux ([], xs)

splitWhen (<) [1;2;3;3;4]
// val it : int list list = [[1; 2; 3; 3; 4]]
splitWhen (<) [1;2;3;2;4;3;5]
// val it : int list list = [[1; 2; 3]; [2; 4]; [3; 5]]

Edit2

您也可以不使用累加器,而可以使用列表推导(也称为列表sequence expression)。这是一种作弊,因为它需要使用累加器的辅助功能。它将产生签名let rec splitList<'T when 'T: comparison> (acc : 'T list list) (list: 'T list) : 'T list list = match acc, list with | (y::_) as ys::yss, x::xs -> if x >= y then splitList ((x::ys)::yss) xs else splitList ([x]::acc) xs | _, x::xs -> splitList [[x]] xs | _ -> List.rev (List.map List.rev acc) splitList [] [1;2;3;3;4] // val it : int list list = [[1; 2; 3; 3; 4]] splitList [] [1;2;3;2;4;3;5] // val it : int list list = [[1; 2; 3]; [2; 4]; [3; 5]]

val splitList : list:'a list -> 'a list list when 'a : comparison