2010-05-26 11 views
9

tengo una lista como esta:Erlang: aplanamiento de una lista de cadenas

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

Y necesito para convertirlo en

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

¿Cómo se hace esto?

El problema es que estoy tratando con listas de cadenas, por lo que cuando lo haga

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

me sale

"str1str2str3str4str5str6" 

Sin embargo, si los elementos de la lista original, donde solo los átomos, entonces lists:flatten me habría dado lo que necesitaba. ¿Cómo logro lo mismo con cadenas?

Respuesta

12

listas: append es exactamente lo que necesita:

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

(listas: concat hace lo correcto, pero amenaza con hacer algún tipo de conversión demasiado .)

2

Si la lista es siempre una "lista de lista de cadena", entonces puede simplemente utiliza el operador foldl, con algo como:

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

En el caso de que su lista de anidación puede ser de profundidad arbitraria, yo prefiero sugerir a dejar que Erlang saber sus cadenas no son meras listas de caracteres, utilizando una codificación tales como:

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

de esta manera, list:flatten va a hacer lo correcto, y darle:

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

que puede convertir de nuevo si es necesario a una lista de cadenas sin procesar usando foldl. Si sus cadenas deben manejarse de forma diferente a las simples listas de caracteres, entonces probablemente merecen ser una estructura de datos real, consulte este blog entry para una discusión interesante sobre este asunto.

+0

¡Gracias! Funciona :) – ErJab

+3

Si desea un enfoque más genérico es posible que desee echar un vistazo a io_lib: printable_list/1. es decir, solo aplana si la lista no es imprimible. – Lukas

+0

'list: foldl (fun erlang: '++'/2, [], List)' es incluso más corto. – nox

1

listas: concat 1 obras/...

0

Las listas de motivos: aplanar no funciona para usted es que las cadenas en Erlang son solo listas de enteros pequeños. Podemos manejar esto con una función que detiene el reaprovisionamiento en una lista anidada si la lista es solo una cadena.

Para una lista arbitraria anidado de cadenas que puede utilizar la siguiente función:

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

Se utiliza io_lib: lista_caracteres() para decidir si la recursividad de anidación fue lo suficientemente profunda.

exampe de operación:

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

Una pequeña mejora que haría posible el uso de listas anidadas mixtos:

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

Esto comporta como listas: aplanar excepto que se encarga de cadena como si no serían listas:

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"] 
Cuestiones relacionadas