我正在尝试将具有整数的列表拆分为具有升序值的子列表。
例如:$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]
。
我试图通过尾递归来做到这一点,但是我不知道该怎么做。
答案 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