Erlang: выравнивание списка строк - PullRequest
9 голосов
/ 26 мая 2010

У меня есть такой список:

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

И мне нужно преобразовать его в

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

Как мне это сделать?

Проблема в том, что я имею дело со списками строк, поэтому, когда я делаю

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

Я получаю

"str1str2str3str4str5str6"

Однако, если бы элементы исходного списка были просто атомами, то lists:flatten дал бы мне то, что мне было нужно. Как мне добиться того же самого со строками?

Ответы [ 4 ]

12 голосов
/ 26 мая 2010

списков: приложение делает именно то, что вам нужно:

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

(списки: concat делает правильные вещи, но угрожает также выполнить некоторое преобразование типов.)

2 голосов
/ 26 мая 2010

Если ваш список всегда является «списком списка строк», то вы можете просто использовать оператор foldl, например:

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

В случае если вложенность вашего списка может быть произвольной глубины, я бы предпочел, чтобы erlang знал, что ваши строки не являются простыми списками символов, используя такую ​​кодировку, как:

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

Таким образом, list:flatten поступит правильно и выдаст:

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

, который при необходимости можно преобразовать обратно в необработанный список строк, используя foldl. Если ваши строки должны обрабатываться иначе, чем просто списки символов, то они, вероятно, заслуживают того, чтобы быть реальной структурой данных, см. Эту запись в блоге для интересного обсуждения этого вопроса.

1 голос
/ 26 мая 2010

списков: конкат / 1 работ ...

0 голосов
/ 11 июня 2010

Причины списков: flatten у вас не работает, потому что строки в Erlang - это просто списки маленьких целых чисел. Мы можем справиться с этим с помощью функции, которая перестает повторяться во вложенном списке, если список является просто строкой.

Для произвольно вложенного списка строк вы можете использовать следующую функцию:

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

Он использует io_lib: char_list (), чтобы решить, была ли вложенная рекурсия достаточно глубокой.

Пример операции:

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

Небольшое улучшение, которое позволило бы использовать смешанные вложенные списки:

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)].

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

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"]
...