Помогите мне объяснить функцию транспонирования матрицы F # - PullRequest
14 голосов
/ 10 июня 2010

Существует Матрица транспонирования функция:

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"

Работает нормально.
Что означает (_ :: _) :: _ ?
Я не понимаю весь код!
Кто может это объяснить?
Спасибо!

Я нашел ответ:
(_ :: _) :: _ - это шаблон, соответствующий значению типа список списков целых чисел


Еслия пишу:

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

Это вызывает исключение во время выполнения.Что-то не так с hd ?
Да , что-то вроде [[]; []; []] при вызове Список.tail , затем он вызывает исключение при вызове List.head !


Проблема решена!
Спасибо всем!

Ответы [ 5 ]

26 голосов
/ 10 июня 2010

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

То же самое можно написать так.Это более многословно, но должно быть понятно, что здесь происходит:

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
    | _ -> []
  | _ -> [] 

Как видите, нам не нужны значения row, rows, col иcols.Вот почему оригинальная реализация заменяет их на _ (который игнорирует значение и проверяет только то, что список может быть разложен требуемым образом).

В рекурсивном случае мы деконструируем матрицу следующим образом:

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

Надеюсь, что картинка прояснит для вас!

5 голосов
/ 10 июня 2010

Это также может помочь вам:

Понимание функции преобразования матрицы в Haskell

Это очень похожая функция в аналогичном языке программирования (Haskell).

3 голосов
/ 10 июня 2010

(_::_)::_ соответствует шаблону._ - это просто неиспользуемая переменная.Это будет эквивалентно:

(a::b)::c as M -> List.map List.head M :: transpose (List.map List.tail M)
1 голос
/ 08 апреля 2017

Прошу прощения, что столкнулся с устаревшей темой, но ваш первоначальный ответ почти верен.Единственное, что неправильно, это условие завершения для пустого списка.Код должен выглядеть примерно так:

let rec transpose M = 
    match M with 
    | []::_ -> []
    | _ -> List.map List.head M::transpose(List.map List.tail M)
1 голос
/ 26 июня 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...