2014-12-22 7 views
0

У меня есть список номеров и вы хотите получить список расстояний между номерами. Например:Найти расстояние между элементами списка

[1; 3; 8; 10; 12] → [2; 5; 2; 2] 

Вот мой код:

let rec diffs lst acc = 
    match List.length lst > 1 with 
    | true -> 
     let first = List.head lst 
     let second = List.head (List.tail lst) 
     diffs (List.tail lst) (List.append acc [second - first]) 
    | false -> acc 

Я просто интересно, если есть лучшее решение?

+0

Возможно, лучше для codereview.se, но есть определенная возможность для улучшения –

ответ

3

Перевод на более идиоматических

let rec diffs lst = 
    match lst with 
    | head::head2::tail -> (head2-head)::(diffs (head2::tail) 
    | _ -> [] 
8

Вероятно, самый простой способ использовать то, что F # дает вам из коробки:

let diffs = 
    Seq.pairwise 
    >> Seq.map (fun (a,b) -> b - a) 
    >> List.ofSeq 

В общем, вызовы List.head, tail или append, особенно если они появляются в рекурсивной функции, это небольшие запахи кода в моей книге. Они обычно означают, что функция может быть написана другим, более упорядоченным способом (пример в данном случае - подход Джона Джон в другом ответе, который вы можете легче сопоставить с кодом, с которого вы начали).

Еще один совет - вы расширяете свой аккумулятор, используя (List.append acc [second - first]), что очень расточительно. Вам нужно пройти и скопировать весь список, чтобы добавить элементы в конце. Обычная модель состоит в том, чтобы добавить элементы из головы ((second - first) :: acc) и повернуть обратно накопитель при возврате.