2010-10-21 98 views
6

Tôi đang cố gắng thực hiện chức năng đệ quy để chuyển danh sách danh sách, n x p thành p x n. Nhưng tôi không thể làm như vậy. Tôi đã có thể để thực hiện một chức năng để transpose một danh sách 3 x n của danh sách này để một n x 3 một:chuyển đổi danh sách các danh sách

let rec drop1 list= 
    [(match (List.nth list 0) with [] -> [] | a::b -> b); 
    (match (List.nth list 1) with [] -> [] | a::b -> b); 
    (match (List.nth list 2) with [] -> [] | a::b -> b);] 

let rec transpose list= 
    if List.length (List.nth list 0) == 0 then [] 
    else [(match (List.nth list 0) with [] -> 0 | a::b -> a); 
      (match (List.nth list 1) with [] -> 0 | a::b -> a); 
      (match (List.nth list 2) with [] -> 0 | a::b -> a)] 
     :: transpose (drop1 list) 

Nhưng tôi không thể khái quát nó. Tôi chắc chắn đang suy nghĩ sai hướng. Đây có phải là khái quát? Có giải pháp nào tốt hơn không? Hãy giúp tôi.

Trả lời

10
let rec transpose list = match list with 
| []    -> [] 
| [] :: xss -> transpose xss 
| (x::xs) :: xss -> 
    (x :: List.map List.hd xss) :: transpose (xs :: List.map List.tl xss) 
+1

+1, Wow! Tôi đã không nhận thức được chức năng List.map. Hướng dẫn sử dụng nói nó không phải đệ quy đuôi. Hiệu ứng nào có thể có nếu tôi sử dụng nó trong một mã lớn hơn? – lalli

+1

@ lalli: Đối với các danh sách rất lớn, nó có thể gây ra tràn ngăn xếp. Trong trường hợp đó, bạn nên sử dụng 'List.rev_map' thay vào đó và sau đó đi qua các danh sách ở cuối và đảo ngược chúng. Tuy nhiên, lưu ý rằng định nghĩa 'transpose' của tôi cũng không phải là đệ quy đuôi (không phải của bạn). – sepp2k

+4

Bạn không nên lo lắng về tính đệ quy đuôi lúc đầu; cố gắng thực hiện đơn giản và rõ ràng. Sử dụng chức năng "chuyển vị" trên ('danh sách danh sách) có danh sách rất lớn có thể là một ý tưởng rất tồi. Nếu bạn có nhiều dữ liệu, một cấu trúc dữ liệu khác (ví dụ: ma trận được chỉ mục bởi (int * int), có một hàm 'transpose' liên tục thời gian) có lẽ phù hợp hơn. – gasche

Các vấn đề liên quan