如何清理特定字符串的列表并返回已清理的列表或NONE

时间:2013-01-23 17:57:00

标签: functional-programming sml smlnj

我需要编写一个函数来回答这些规范:

clean_list( [],s1] = NONE

clean_list( xs, "") = NONE

clean_list ([s1, s1, s1, s1], s1) = NONE

clean_list([s1, s2, s3, s2, s1], s3) = [s1, s2, s2, s1]

其中s1s2s3是一些字符串,xs是字符串列表。

我能够使用两个辅助函数is_into(xs: string list, s1: string) -> boolremove(xs: string list, s1: string) -> string list来完成它,但在列表中两次递归似乎很难看。

clean_list(xs: string list, s1: string) =
    case (xs, s1) of
         ( [], _ ) => NONE
        |( _, "" ) => NONE
        |( _, _) => if is_into(xs, s1)
                    then remove(xs, s1)
                    else NONE

有没有办法在列表中没有递归两次(is_into一次,remove一次)?

注意:不使用任何内置函数。

对不起,我忘记了规范

中的重要案例
clean_list ([s1, s2, s3, s4], s10] = NONE

1 个答案:

答案 0 :(得分:1)

您可以轻松地逐个浏览列表,逐个元素并删除与给定字符串匹配的所有内容,最后返回SOME lst,其中lst是结果列表

fun clean_list ([], _ ) = NONE
  | clean_list (_, "") = NONE
  | clean_list (xs, str) =
    let
      fun clean_list' [] = []
        | clean_list' (x::xs) =
          if x = str then
            clean_list' xs
          else
            x :: clean_list' xs
    in
      SOME (clean_list' xs)
    end

<强>更新

我注意到上面的代码实际上没有处理这种情况:clean_list ([s1, s1, s1, s1], s1) = NONE。但是这很容易解决。

我可以看到,根据您的新更新规范,如果元素首先不在列表中,则应返回NONE。这与说法相同,如果在浏览所有元素时没有删除任何元素,则返回NONE

希望您可以看到这可以通过向辅助函数添加一个额外的布尔参数来实现,最初将其设置为false,然后在每次递归调用中传递其值,除非在删除元素的情况下,在这里它总是可以设置为true。

然后,可以使用此选项确定天气以返回SOME lst,其中lst是结果列表,或NONE如果没有删除任何元素。

鉴于这两件事需要修复,将辅助函数建立在累积参数中的结果可能是个好主意。通过这种方式,您可以完全控制,并且当累积列表最后为空时可以轻松返回NONE