简体   繁体   中英

A function in SML that slices a list?

I am trying to write a function in SML that would slice a list.

Slice xy ls

ex. Slice 1 3 [0,1,2,3,4] and the output [1,2,3]

This is what I have to start

fun slice(aList, start, stop) = nil;
fun slice(nil, x, y) = []
  | slice(ls, x, y) =

In SML write a slice function, with functionality similar to the Python list slice operator.

For example, slice ([11, 22, 3, 14, 5, 6], 1, 4) returns the list [22, 3, 14]

Return a slice of a list between indices start inclusive, and stop exclusive. Assume first element of list is at index 0 .

Thank you! I appreciate the help!

How do you know what index you're currently on?

You have to pass that information into the function. Let's call that cur for "current."

Slicing an empty list returns an empty list. Slicing a non-empty list should look at the first element in the list, and the current index and if the current index falls into the range provided by start and stop , add it to the output by appending it onto the result of running the same function on the rest of the list.

fun slice([], start, stop, cur) = []
  | slice(x::xs, start, stop, cur) =
    if cur >= start andalso cur <= stop then
      x :: slice(xs, start, stop, cur + 1)
    else
      slice(xs, start, stop, cur + 1)

This works quite nicely, but seeing that current index of 0 passed to the function is ugly. Let's hide that with a local helper funciton.

fun slice(lst, start, stop) =
  let
    fun aux([], start, stop, cur) = []
      | aux(x::xs, start, stop, cur) =
        if cur >= start andalso cur <= stop then
          x :: aux(xs, start, stop, cur + 1)
        else
          aux(xs, start, stop, cur + 1)
  in
    aux(lst, start, stop, 0)
  end

And this is good, but can we make it tail-recursive? We can, but we need n accumulator that we pass from one recursive call to the next building up the resulting list. Also, in our base case for aux , we don't need to name start , stop , or cur as they are irrelevant to the outcome.

fun slice(lst, start, stop) =
  let
    fun aux([], _, _, _, acc) = List.rev(acc)
      | aux(x::xs, start, stop, cur, acc) =
        if cur >= start andalso cur <= stop then
          aux(xs, start, stop, cur + 1, x::acc)
        else
          aux(xs, start, stop, cur + 1, acc)
  in
    aux(lst, start, stop, 0, [])
  end

If you are using sml/nj, which includes a nice set of built-ins on the List structure , you can just do this:

fun slice (a,b) xs = List.take (List.drop (xs,a), b-a)

That would match the basic (non-negative index) functionality of the python's slice operator.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM