如何从ocaml中的列表中获取子列表

时间:2010-04-25 22:31:40

标签: list ocaml

我正在查看List文档。似乎图书馆没有提供sublist功能。

我正在尝试从 i j 获取元素列表。现在我必须把它写成:

let rec sublist list i j =
  if i > j then
    []
  else
    (List.nth list i) :: (sublist list (i+1) j)

这是非常简洁的,但我在质疑List.nth的效率,因为如果它是 O(n),我宁愿以不那么简洁的方式写它。 / p>

我想知道为什么他们不提供List.sublist func,如果List.nth不是 O(1),因为这是一个非常常见的操作.. < / p>

4 个答案:

答案 0 :(得分:10)

let rec sublist b e l = 
  match l with
    [] -> failwith "sublist"
  | h :: t -> 
     let tail = if e=0 then [] else sublist (b-1) (e-1) t in
     if b>0 then tail else h :: tail
;;

sublist 3 5 [1;2;3;4;5;6;7;8;9] ;;
- : int list = [4; 5; 6]

以上或多或少是newacct解决方案的砍伐版本。 newacct的解决方案分配一个中间列表(drop i list),编译器可以在Haskell中优化,但在ML中更难。因此,他的版本对于Haskell函数来说非常好,对于ML函数来说略微次优。两者之间的差异只是一个常数因素:两者都是O(e)。 zrr的版本是O(长度(长度)),因为List.filteri不知道f只在一段时间后返回false,它会为l中的所有元素调用它。

我不是很高兴让b变为否定,但不是更复杂的版本。

如果您感兴趣,可以参考一些针对森林砍伐的文章:http://homepages.inf.ed.ac.uk/wadler/topics/deforestation.html

答案 1 :(得分:6)

首先尝试编写take(前n项)和drop(除前n项之外的所有项)函数(如Haskell中)。然后sublist i j lst只是take (j-i) (drop i lst)

答案 2 :(得分:2)

这比使用OCaml的标准库要困难一点---标准库有点稀疏。如果您使用其中一个扩展标准库,则会更容易。例如,使用Core,您可以写:

let sublist list low high =
   List.filteri l ~f:(fun i _ -> i >= low && pos < high)

我认为使用extlib / battery可以实现类似的功能。

答案 3 :(得分:0)

虽然Pascal提供的答案为Array.sub实现了一个很好的候选者,但正确的答案是你应该更好地使用列表数组。 Array模块实现了您可能使用的$htmltop = "<html><head></head><body><ul>" $htmlbottom = "</ul></body></html>" $wpath = Get-ChildItem F:\@software\ -recurse $outp = $wpath | Where-Object {$_.extension -eq ".wav" -and $_.name -like "*hou*"} $outp = $outp | % { $("<li><a href='file://" + $($_.FullName) + "'>" + $($_.Name) + "</a></li>")} $htmltop | Out-File F:\@software\htmlout99.html -Append $outp | Out-File F:\@software\htmlout99.html -Append $htmlbottom | Out-File F:\@software\htmlout99.html -Append ii F:\@software\htmlout99.html 函数。

虽然在许多命令式语言(如C ++或Perl)中,列表和数组之间基本没有区别,但在OCaml中这是不同的:

  • 列表更适合递归处理和顺序访问,通常更适合作为数组作为递归函数的参数,你通常想看看所有列表的元素。

  • 数组更适合随机访问,结构更改(如排序)或数值计算。