Erlang: выравнивание списка строк

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

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

И я должен преобразовать его в

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

Как я делаю это?

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

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

Я добираюсь

"str1str2str3str4str5str6"

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

9
задан ErJab 26 May 2010 в 08:53
поделиться

4 ответа

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

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

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

12
ответ дан 4 December 2019 в 13:45
поделиться

Если ваш список всегда является "списком списков строк", то вы можете просто использовать оператор 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. Если ваши строки должны обрабатываться иначе, чем просто списки символов, то они, вероятно, заслуживают того, чтобы быть настоящей структурой данных, см. эту запись в блоге для интересного обсуждения этого вопроса.

2
ответ дан 4 December 2019 в 13:45
поделиться

списки: concat / 1 работает ...

1
ответ дан 4 December 2019 в 13:45
поделиться

Причина, по которой lists: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)].

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

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"]
0
ответ дан 4 December 2019 в 13:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: