2010-05-26 36 views
9

tôi có một danh sách như thế này:Erlang: làm phẳng một danh sách các chuỗi

[["str1","str2"],["str3","str4"],["str5","str6"]] 

Và tôi cần phải chuyển nó sang

["str1", "str2", "str3", "str4", "str5", "str6"] 

Làm thế nào để làm điều này?

Vấn đề là tôi đang đối phó với danh sách các chuỗi, vì vậy khi tôi làm

lists:flatten([["str1","str2"],["str3","str4"],["str5","str6"]]) 

tôi nhận được

"str1str2str3str4str5str6" 

Tuy nhiên, nếu các yếu tố của danh sách ban đầu mà chỉ nguyên tử, sau đó lists:flatten sẽ cho tôi những gì tôi cần. Làm thế nào để đạt được cùng một chuỗi?

Trả lời

12

danh sách: append thực hiện chính xác những gì bạn cần:

1> lists:append([["str1","str2"],["str3","str4"],["str5","str6"]]). 
["str1","str2","str3","str4","str5","str6"] 

(danh sách: concat làm điều đúng, nhưng đe dọa để làm một số chuyển đổi loại quá .)

2

Nếu danh sách của bạn luôn luôn là một "danh sách danh sách các chuỗi", sau đó bạn chỉ có thể sử dụng foldl điều hành, với một cái gì đó như:

Flat = list:foldl(fun(X, Acc) -> X ++ Acc end, [], List) 

Trong trường hợp danh sách làm tổ của bạn có thể có chiều sâu tùy ý, tôi thà đề nghị để cho erlang biết dây của bạn không phải là danh sách nhân vật đơn thuần, sử dụng một mã hóa như:

[[{string, "str1"},{string, "str2"}], 
[{string, "str3"}, {string, "str4"}], 
[{string, "str5"},{string, "str6"}]] 

bằng cách này, list:flatten sẽ làm điều đúng, và cung cấp cho:

[{string, "str1"},{string, "str2"}, 
{string, "str3"}, {string, "str4"}, 
{string, "str5"},{string, "str6"}] 

mà bạn có thể chuyển đổi lại nếu cần thiết thành danh sách chuỗi thô sử dụng foldl. Nếu các chuỗi của bạn được xử lý khác với các danh sách ký tự đơn thuần, thì chúng có thể xứng đáng là một cấu trúc dữ liệu thực, hãy xem blog entry này để có một cuộc thảo luận thú vị về vấn đề này.

+0

Cảm ơn! Nó hoạt động :) – ErJab

+3

Nếu bạn muốn một cách tiếp cận chung chung hơn, bạn có thể muốn có một cái nhìn tại io_lib: printable_list/1. tức là chỉ làm phẳng nếu danh sách không thể in được. – Lukas

+0

'danh sách: foldl (fun erlang: '++'/2, [], List)' thậm chí còn ngắn hơn. – nox

1

danh sách: concat/1 công trình ...

0

Lý do danh sách: flatten không hoạt động cho bạn là các chuỗi trong Erlang chỉ là danh sách các số nguyên nhỏ. Chúng ta có thể xử lý điều này với một hàm dừng đệ quy trong một danh sách lồng nhau nếu danh sách chỉ là một chuỗi.

Đối với danh sách tùy tiện lồng nhau của chuỗi bạn có thể sử dụng chức năng sau:

slab([]) -> 
    []; 
slab([F|R]) -> 
    case io_lib:char_list(F) of 
     true -> [F|slab(R)]; 
     false -> slab(F) ++ slab(R) 
    end. 

Nó sử dụng io_lib: char_list() để quyết định xem đệ quy làm tổ là đủ sâu.

exampe hoạt động:

1> slab([[["foo", "bar"], "baz", [[[["foobar"]]]], "froboz", "the end"]]). 
["foo","bar","baz","foobar","froboz","the end"] 
2> 

Một cải tiến nhỏ mà có thể làm cho nó có thể sử dụng danh sách lồng nhau hỗn hợp:

slab([]) -> 
    []; 
slab([F|R]) when is_list(F) -> 
    case io_lib:char_list(F) of 
     true -> [F|slab(R)]; 
     false -> slab(F) ++ slab(R) 
    end; 
slab([F|R]) -> 
    [F|slab(R)]. 

này hoạt động giống như danh sách: flatten ngoại trừ việc nó xử lý chuỗi như nếu họ sẽ không có danh sách:

1> slab([[["foo", "bar"], "baz", [[[["foobar", atom]],[a,b,c]]], 2, "froboz", "the end"]]). 
["foo","bar","baz","foobar",atom,a,b,c,2,"froboz","the end"] 
Các vấn đề liên quan