Преобразование из Python в F # рекурсивной функции? - PullRequest
0 голосов
/ 19 марта 2020

Я пытаюсь преобразовать этот Python код в F # без использования неизменяемых переменных или List.map. Я все еще новичок ie в этом.

def findMatches(s,l):
    temp=[]
    for i in l:
        if i[0]==s:
            temp.append(i[1])
    temp.sort()
    return temp

l=findMatches("A",[("A",5),("AA",9),("BB",6),("A",0)])
print(l)

Я начал с:

let findMatches s l =
    for e1, e2 in list do
        if e1 = s then ...

Не совсем, если я иду в правильном направлении или куда go дальше.

Ответы [ 2 ]

5 голосов
/ 19 марта 2020

В Python довольно распространенной практикой является изменение («изменение», «обновление») ваших данных по мере того, как вы go перемещаетесь - как вы делаете со своим списком temp, изменяя его в каждый шаг. Несмотря на то, что он, как правило, осуждается даже в Python, сам язык делает его очень простым и, следовательно, очень заманчивым.

В F # мутация данных все еще возможна, но язык усложняет ее. Нарочно. Ну, не , что сложно - это всего лишь несколько лишних символов, - но, по крайней мере, изменяющиеся данные не используются по умолчанию. Это в целом лучший подход, так как даже сообщество Python теперь признает.

Вместо этого, путь F # (и, вообще говоря, функциональный способ) не состоит в мутировании данные, но для создания новых данных путем преобразования старых. Например, что делают функции (где под «функциями» я подразумеваю «математические функции»).

В частности, то, что, похоже, делает Python l oop, это (1) фильтрация список ввода с помощью i[0], а затем (2) преобразование (обычно называемое «отображением») каждого элемента путем отбрасывания i[0] и оставления только i[1], а затем (3) сортировки. Это можно записать на F # следующим образом:

let findMatches s l =
    l
    |> List.filter (fun (e1, _) -> e1 == s)  // filtering
    |> List.map (fun (_, e2) -> e2)          // mapping
    |> List.sort

Вместо того, чтобы «строить» список путем многократного его изменения, эта программа создает результирующий список путем преобразования входного списка трижды: фильтрация, затем сопоставление, затем сортировка. Следует также отметить, что сами преобразования создаются из более мелких частей: преобразование всего списка достигается путем преобразования преобразования одного элемента.

Для простых случаев, подобных этому (кроме сортировки), В F # также предусмотрен специальный синтаксис - так называемые «списки». Это syntacti c sugar, который за кулисами выполняет преобразования, аналогичные приведенным выше, но синтаксис (возможно) более читабелен:

let findMatches s l =
    [ for e1, e2 in l do
        if e1 == s then yield e2
    ]
    |> List.sort

Обратите внимание, что, хотя это выглядит почти идентично вашему Python Программа, смысл немного отличается. Вместо того, чтобы «сделать это, затем сделать это» (он же «императивный стиль»), эта программа говорит «результат зависит от ввода таким образом» (он же «функциональный стиль»).

0 голосов
/ 19 марта 2020

Самое прямое сопоставление примера кода Python с F #, о котором я мог подумать:

// I tend to specify the signatures of methods as I find it helpful
let findMatches (s : 'K) (l : seq<'K*'V>): seq<'V> =
  // ResizeArray is an alias for System.Collections.Generic.List<_>
  let temp = ResizeArray ()
  for e1, e2 in l do
    if e1 = s then
      temp.Add e2
  temp.Sort ()
  // F# don't do implicit upcasts like C# so an explicit upcast from
  //  ResizeArray to seq
  upcast temp

Как упомянул Федор в F # идиома (ie общий подход), состоит в том, чтобы избежать изменчивости и предпочитают встроенные функции высшего порядка (например, фильтр и отображение) для обработки списков.

...