удаление стоп-слов в F # - PullRequest
       11

удаление стоп-слов в F #

0 голосов
/ 23 февраля 2012

Я пытаюсь написать код для удаления таких слов, как "the", "this", в списке строк и т. Д.

Я написал этот код:

let rec public stopword (a : string list, b :string list) =

    match [a.Head] with
        |["the"]|["this"] -> stopword (a.Tail, b)
        |[] -> b
        |_ ->  stopword (a.Tail, b@[a.Head])

Я запустил этов интерактиве:

stopword (["this";"is";"the"], []);;

Я получил эту ошибку:

This expression was expected to have type string list but here has type 'a * 'b

Ответы [ 3 ]

4 голосов
/ 23 февраля 2012

Выражения соответствия в F # очень мощные, хотя синтаксис поначалу сбивает с толку

Вам нужно сопоставить список следующим образом:

let rec stopword a =
    match a with
    |"the"::t |"this"::t -> stopword t
    |h::t ->h::(stopword t)
    |[] -> []
2 голосов
/ 23 февраля 2012

Другие упоминали силу сопоставления с образцом в этом случае. На практике у вас обычно есть набор стоп-слов, которые вы хотите удалить. А защита when позволяет нам вполне соответствовать шаблону:

let rec removeStopwords (stopwords: Set<string>) = function
    | x::xs when Set.contains x stopwords -> removeStopwords stopwords xs 
    | x::xs -> x::(removeStopwords stopwords xs)
    | [] -> []

Проблема с этой функцией и ответом @ John заключается в том, что они не являются хвостово-рекурсивными. Они заканчиваются в длинном списке, состоящем из нескольких стоп-слов. Хорошая идея - использовать функции высокого порядка в Списочном модуле , которые имеют хвостовую рекурсию:

let removeStopwords (stopwords: Set<string>) xs =
    xs |> List.filter (stopwords.Contains >> not)
2 голосов
/ 23 февраля 2012

Фактическая ошибка связана с тем, что функция ожидает аргумент кортежа.Вам нужно будет вызвать функцию с помощью:

let result = stopword (["this";"is";"the"], [])

Редактировать: поскольку исходный вопрос был изменен, приведенный выше ответ больше не действителен;логическая ошибка в реальной функции заключается в том, что в итоге получается один элемент списка, из которого берется хвост, в результате чего получается пустой список.При следующем рекурсивном вызове функция захлебывается при попытке получить заголовок этого пустого списка

Сама по себе функция реализована неправильно, хотя и намного сложнее, чем необходимо.

let isNoStopword (word:string) =
    match word with
    | "the"|"this" -> false
    | _ -> true

let removeStopword (a : string list) =
    a |> List.filter(isNoStopword)

let test = removeStopword ["this";"is";"the"]
...