F # Удалить дубликаты

#list #recursion #f#

#Список #рекурсия #f#

Вопрос:

Я пытаюсь удалить дубликаты в списке с помощью этой функции. Он удаляет дубликаты, но возвращает список в обратном порядке. Я немного не уверен, как это исправить без уродливого решения.

Комментарии:

1. Использовать foldback ?

2. Не знаю, что это такое.

3. внутренняя лямбда-строка в removeDuplicates должна иметь имя func или add , но оставаться неизменной в коде; тем не менее, вам просто нужно изменить результирующий список, либо используя List.rev , либо написав свой собственный.

4. @Sehnsucht Как будет выглядеть такая обратная функция?

5. Вы можете просто использовать do [] -> List.rev nlist

Ответ №1:

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

 let rd list= 
   let rec func list nlist=
      match list with
      | [] -> List.rev nlist // Reverse the list before returning it
      | x::xs ->
         if not (isMember x nlist) then 
            func xs (x::nlist)
         else
            func xs nlist
   func list []
  

Помимо добавления List.rev , я также изменил последнюю строку на func list [] (там был ваш код add , но это, вероятно, была опечатка). Я также перешел isMember x nlist <> true на более идиоматический not (isMember x nlist) .

Комментарии:

1. может быть еще более идиоматичным просто инвертировать if , else блокировать и удалять not

Ответ №2:

Вы можете сделать это, чтобы удалить дубликаты:

 Seq.distinct [1;1;2;4;4;5;6]
  

Он возвращает [1;2;4;5;6]

Комментарии:

1. На самом деле это не та практика, к которой я стремлюсь>. <

Ответ №3:

Мне не совсем понятно, какую помощь (или ее отсутствие) вы хотите получить от стандартных библиотечных функций в вашем решении.

Самый простой подход — просто использовать List.distinct

 List.distinct [1;1;2;4;4;5;6];;
val it : int list = [1; 2; 4; 5; 6]
  

Вы могли бы создать версию, используя foldBack

 let distinct lst = 
    List.foldBack (fun v lst' -> 
        if List.contains v lst' then lst'
        else v::lst') lst []
  

Это приводит к тому же результату:

 distinct [1;1;2;4;4;5;6];;
val it : int list = [1; 2; 4; 5; 6]
  

Если вы тоже хотите создать свой собственный foldBack

 let rec foldBack f lst z =
    match lst with
    |[] -> z
    |x::xs -> f x (foldBack f xs z)
  

Обратите внимание, что я пытаюсь не писать одну большую функцию, которая делает все, а вместо этого пытаюсь создать решение из серии повторно используемых компонентов — это хорошая привычка при работе на функциональных языках.