2016-02-20 2 views
1

Я пытаюсь обменять два элемента в списке, не совсем уверен, почему мины не работают.OCaml swapping элементы в списке

Правильная реализация должна сделать следующее:

list_swap_val [5;6;7;3] 75 => [7;6;5;3] 
list_swap_val [5;6;3] 7 5 => [7;6;3] 

Вот две реализации, которые я пробовал, но оба, кажется, просто вернуть первоначальный список

let rec list_swap l u v = 
    match l with 
    |[] -> [] 
    |h::t -> if h = u then u::(list_swap t u v) 
      else if h = v then v::(list_swap t u v) 
      else h::(list_swap t u v) ;; 

Я также пытался сделать выше но в то время как в операциях совпадения вместо использования if, но оба они не работают. Где я иду не так? Спасибо за любую помощь

+0

Какое сообщение об ошибке у вас есть? Пожалуйста, будьте более конкретными. Кроме того, посмотрите на «a», «b», затем посмотрите на «u» и «v» ;-) – coredump

+0

О, извините, я хотел сохранить параметры одинаковыми. Я просто получаю тот же список, и ничего не изменилось, когда я пытаюсь выполнить код в примерах. –

+0

Когда вы видите 'u', первый элемент в возвращаемом списке должен быть' v' (и наоборот для 'v 'и' u'). Здесь, как если бы вы создавали 'h: :(list_swap t u v)' во всех случаях. Прошло некоторое время с тех пор, как я закодировал в OCaml, но я думаю, вы можете избежать использования шаблона if и use, чтобы различать все случаи. – coredump

ответ

4

Вы забыли на самом деле обмен значениями: когда вы видите u, первым элементом вашего возвращенного списка должно быть v. Здесь, как если бы вы построили h::(list_swap t u v) во всех случаях. Кстати, вы можете Факторизуете рекурсивный вызов, который дает вам, наконец, это определение:

let rec list_swap l u v = 
    match l with 
    | [] -> [] 
    | h::t -> (if h = u then v 
       else if h = v then u 
        else h)::(list_swap t u v);; 
4

Как coredump- писал вы можете факторизовать, но вы можете пойти еще дальше и заметить, что это карта.

let swap u v x = if x = u then v else if x = v then u else x 
let list_swap u v = List.map (swap u v) 
1

как указано выше, вы забыли обменять. Вы можете также использовать List.map:

let swap u v n = match n with 
    |x when x = u -> v 
    |x when x = v -> u 
    |_ -> n;; 
let list_swap l u v = List.map (swap u v) l;; 

Это вызывает функцию «своп у v» (благодаря частичной оценке) на каждом элементе в списке «л».

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

let list_swap l u v = List.rev (List.rev_map swap (u v) l);; 

«rev_map» такой же, как «карта» за исключением того, переворачивает список в то же время, и это хвостовая рекурсия. Таким образом, вы снова меняете список. «rev» также является хвостом рекурсивным!

Смежные вопросы