2010-06-10 19 views
14
transpozycji

Jest Matrix transpozycji funkcję:Pomóż mi wyjaśnić F # Matrix funkcję

let rec transpose = function 
    | (_::_)::_ as M -> List.map List.head M :: transpose (List.map List.tail M) 
    | _ -> [] 

[[1; 2; 3]; [4; 5; 6]; [7; 8; 9]] |> transpose |> printfn "%A" 

to działa dobrze.
Co znaczy (_ :: _) :: _?
Nie rozumiem całego kodu!
Kto może to wyjaśnić?
Dziękujemy!

znajdę odpowiedź:
(_ :: _) :: _ jest wzorzec dopasowania na wartości typu wykaz wykazów wskazówki


Jeśli piszę:

let rec transpose (M:int list list) = 
    match M with 
    | hd::tl -> List.map List.head M :: transpose (List.map List.tail M) 
    | _ -> [] 

Rzuca wyjątek środowiska wykonawczego. Czy coś jest nie tak z hd?
Tak, to zrobić coś podobnego [[] [] []] gdy wezwanie List.tail, to zgłasza wyjątek, gdy wezwanie List.head!


Problem rozwiązany!
Dziękuję wszystkim!

Odpowiedz

23

Funkcja ta nie jest szczególnie czytelna, co może być powodem nieporozumień. Konstrukcja (_::_)::_ jest wzorcem pasującym do wartości listy typu list intów, która mówi, że pierwszy przypadek powinien zostać uruchomiony po wyświetleniu niepustej listy niepustych list.

To samo można napisać tak. Jest to bardziej rozwlekły, ale powinno być jasne, co się dzieje tutaj:

let rec transpose matrix = 
    match matrix with // matrix is a list<list<int>> 
    | row::rows ->  // case when the list of rows is non-empty 
    match row with // rows is a list<int> 
    | col::cols -> // case when the row is non-empty 
     // Take first elements from all rows of the matrix 
     let first = List.map List.head matrix 
     // Take remaining elements from all rows of the matrix 
     // and then transpose the resulting matrix 
     let rest = transpose (List.map List.tail matrix) 
     first :: rest 
    | _ -> [] 
    | _ -> [] 

Jak widać, nie naprawdę potrzebują wartości row, rows, col i cols. Dlatego oryginalna implementacja zastępuje je _ (które ignoruje wartość i tylko sprawdza, czy lista może zostać rozłożona w wymagany sposób).

W rekurencyjnym przypadku mamy dekonstrukcji matrycę tak:

[ [ x; y; y ];        [ y; y ] 
    [ x; y; y ]; => [ x; x; x] :: transpose [ y; y ] 
    [ x; y; y ] ]        [ y; y ] 

Mam nadzieję, że obraz sprawia, że ​​bardziej jasne dla ciebie!

+0

+1, dobra odpowiedź! – gradbot

3

(_::_)::_ jest dopasowywaniem wzorca. _ jest po prostu nieużywaną zmienną. Byłoby to równoważne:

(a::b)::c as M -> List.map List.head M :: transpose (List.map List.tail M) 
1

To mapuje head na listach, aby wyodrębnić pierwszą kolumnę i używa jej do utworzenia pierwszego wiersza dodanego do wyniku przeniesienia pozostałych kolumn.

1

Przykro mi z powodu nieaktualnego wątku, ale oryginalna odpowiedź jest prawie poprawna. Jedyne, co jest nie tak, to warunek zakończenia dla pustej listy. Kod powinien wyglądać mniej więcej tak:

let rec transpose M = 
    match M with 
    | []::_ -> [] 
    | _ -> List.map List.head M::transpose(List.map List.tail M) 
Powiązane problemy