2010-06-18 6 views
3

J'ai une structure d'enregistrement simple composée d'un en-tête (H) et d'une liste des lignes de données (D) 1: N. Toutes les lignes d'en-tête doivent commencer par un chiffre. Toutes les lignes de données ont un espace blanc. Il peut également y avoir des lignes vides (E) entre les deux qui doivent être ignorées.Erlang - compréhension de liste - remplissage de dossiers

L = [H, D, D, E, H, D, E, H, D, D, D]. 

Je voudrais créer une liste d'enregistrements:

-record(posting,{header,data}). 

en utilisant la compréhension de la liste. Quel est le meilleur moyen de le faire?

Répondre

3

Vous devriez faire quelque chose comme ceci:

make_records(L) when is_list(L) -> 
    F = fun([32|_]=D,{#posting{}=H,Acc}) -> {H,[H#posting{data=D}|Acc]}; 
     ([], Acc) -> Acc; 
     ([F|_]=H, {_,Acc}) when F=<$0, F>=$9 -> {#posting{header=>H}, Acc} 
     end, 
    {_, R} = lists:foldl(F, {undefined, []}, L), 
    R. 

Quoi qu'il en soit je pense que la version simple Erlang ne semble pas trop compliqué et devrait être un peu plus rapide.

make_records2(L) when is_list(L) -> 
    make_records2(L, undefined, []). 

make_records2([], _, R) -> R; 
make_records2([[32|_]=D|T], H, Acc) when is_list(H) -> 
    make_records2(T, H, [#posting{header=H,data=D}|Acc]); 
make_records2([[]|T], H, Acc) -> 
    make_records2(T, H, Acc); 
make_records2([[F|_]=H|T], _, Acc) when F>=$0, F=<$9 -> 
    make_records2(T, H, Acc). 

Modifier: Si vous devez ajouter une meilleure classification de la ligne ou l'analyse syntaxique, l'ajout d'une nouvelle fonction est meilleure, car il améliore la lisibilité.

parse_row([Digit|_]=R) when Digit >= $0, Digit =< $9 -> {header, R}; 
parse_row(R) -> try_spaces(R). 

try_spaces([]) -> empty; 
try_spaces([Sp|R]) when Sp=:=$\s; Sp=:=$\t; Sp=:=$\n -> 
    try_spaces(R); % skip all white spaces from Data field 
try_spaces(Data) -> {data, Data}. 

Vous pouvez l'utiliser comme ceci:

make_records(L) when is_list(L) -> 
    F = fun(Row, {H, Acc}) -> 
      case parse_row(Row) of 
      {data, D} when is_record(H, posting) -> {H,[H#posting{data=D}|Acc]}; 
      empty -> Acc; 
      {header, H} -> {#posting{header=>H}, Acc} 
     end, 
    {_, R} = lists:foldl(F, {undefined, []}, L), 
    R. 

solution Erlang Tail native récursive:

make_records2(L) when is_list(L) -> 
    make_records2([parse_row(R) || R<-L], undefined, []). 

make_records2([], _, R) -> R; 
make_records2([{data, D}|T], H, Acc) when is_list(H) -> 
    make_records2(T, H, [#posting{header=H,data=D}|Acc]); 
make_records2([empty|T], H, Acc) -> 
    make_records2(T, H, Acc); 
make_records2([{header,H}|T], _, Acc) -> 
    make_records2(T, H, Acc). 

Je pense qu'il n'y a pas récursion usage de la raison de la queue du point de vue de la performance:

make_records3(L) when is_list(L) -> 
    make_records3(L, undefined). 

make_records3([], _) -> []; 
make_records3([R|T], H) -> 
    case parse_row(R) of 
    {data, D} when is_list(H) -> [#posting{head=H,data=D}|make_records3(T, H)]; 
    empty -> make_records3(T, H); 
    {header, H2} -> make_records3(T, H2) 
    end. 

... et beaucoup d'autres variantes.

6

Vous devez utiliser des listes: foldl/3 au lieu de la liste des compréhensions dans ce cas. Avec foldl/3, vous pouvez accumuler des valeurs d'en-tête et les données par liste complète L.

0

je devais réduire toutes les lignes de données sous l'en-tête - donc pour le moment est ici ce que j'ai:

sanitize(S) -> trim:trim(S). 

    make_records(L) when is_list(L) -> make_records(L, undefined, []). 

    make_records([], _, R) -> lists:reverse(R); 

    make_records([[32|_]=D|T], H, Acc) when is_tuple(H) -> 
     make_records(T, {element(1,H),[sanitize(D)|element(2,H)]},Acc); 

    make_records([[$\n|_]=D|T], H, Acc) when is_tuple(H) -> 
     make_records(T, H, Acc); 


    make_records([[F|_]=H|T], B, Acc) when F>=$0, F=<$9 -> 
     if is_tuple(B) -> 
      make_records(T, {sanitize(H),[]}, [#posting{header=element(1,B), 
      data=lists:reverse(element(2,B))}|Acc]); 
     true -> 
      make_records(T, {sanitize(H),[]}, Acc) 
     end. 
Questions connexes