Question

I have a big list of some forms with data that needs to be concated with other data from others forms with the same name.

The list format is quite complex and looks like this:

[[{EVAL_SEQ_1, {FORMNAME, ListDataToConcat1}}], [{EVAL_SEQ_2, {FORMNAME, ListDataToConcat2}}], ...]

This is the output that I want:

[[{EVAL_SEQ_1, {FORMNAME, ListDataToConcat1 + ListDataToConcat2}}]}}] ...]

Where:

EVAL_SEQ_1 = Form Sequence Number,
FORMNAME = Form Name
ListDataToConcat = List that Needs to concat

eg.Here is my sample data:

[[{"eval_data_12",
    {<<"prvl_mobable_asset_0000_h200401">>,
     [{'F_01_0100',[1]},
      {'F_01_0090',["3"]},
      {'F_01_0080',[]},
      {'F_01_0070',[9999]},
      {'F_01_0060',[{era,0},{year,[]},{month,[]}]},
      {'F_01_0050',[]},
      {'F_01_0040',[]},
      {'F_01_0030',[]},
      {'F_01_0020',<<>>},
      {'F_01_0010',<<"4 - 8">>}]}}],
  [{"eval_data_11",
    {<<"prvl_mobable_asset_0000_h200401">>,
     [{'F_01_0100',[]},
      {'F_01_0090',["2"]},
      {'F_01_0080',[]},
      {'F_01_0070',[22222]},
      {'F_01_0060',[{era,0},{year,[]},{month,[]}]},
      {'F_01_0050',[]},
      {'F_01_0040',[]},
      {'F_01_0030',[]},
      {'F_01_0020',<<>>},
      {'F_01_0010',<<"4 - 1">>}]}}], ...]

I want the resultant output like this:

[{"eval_data_11",
   {<<"prvl_mobable_asset_0000_h200401">>,
         [{'F_01_0100',[[], [1]]},
          {'F_01_0090',[["2"], ["3"]]},
          {'F_01_0080',[[], []]},
          {'F_01_0070',[[22222], [9999]]},
          {'F_01_0060',[[{era,0},{year,[]},{month,[]}], [{era,0},{year,[]},{month,[]}]]},
          {'F_01_0050',[[], []]},
          {'F_01_0040',[[], []]},
          {'F_01_0030',[[], []]},
          {'F_01_0020',[[<<>>], [<<>>]]},
          {'F_01_0010',[[<<"4 - 1">>], [<<"4 - 8">>]}]}}]
Was it helpful?

Solution

I propose you this solution:

[edit]

I modified the code to answer your last comment, there are still fuzzy things:

  • if Assets are different, creates different record list?
  • if not what should be done with Asset name? I have chosen to keep the "smallest one"
  • is the order of records important - I decided no

One remark, I am missing some context, but If I add to collect such informations, I would store it in an ets table. It is faster to update, easy to traverse, and easy to transform into list if needed.

-module (t).

-compile([export_all]).

%      rec = {atom,term}
%      reclist = [rec,...]
%      asset = {bin,reclist}
%      eval_data = [{list,asset}]
%      eval_set = [eval_data,...]
%      recs = {atom,[term]}
%      recslist = [recs,...]

addrec({Key,Val},Recslist) ->
    Val_list = proplists:get_value(Key, Recslist, []),
    [{Key,[Val|Val_list]}|proplists:delete(Key,Recslist)].

merge_rec(Reclist,Recslist) -> lists:foldl(fun(Rec,Acc) -> addrec(Rec,Acc) end,Recslist,Reclist).


merge_eval([{Eval,{Asset,Reclist}}],[]) ->
    [{Eval,{Asset,[{Key,[Val]} || {Key,Val} <- Reclist]}}];
merge_eval([{Eval,{Asset,Reclist}}],[{Eval_low,{Asset_low,Recslist}}]) ->
    [{min(Eval,Eval_low),{min(Asset,Asset_low),merge_rec(Reclist,Recslist)}}].

merge_set(Eval_set) -> lists:foldl(fun(Eval_data,Acc) -> merge_eval(Eval_data,Acc) end,[],Eval_set).

test() ->
    Eval_set =  [[{"eval_data_10",
                {<<"prvl_mobable_asset_0000_h200401">>,
                 [{'F_01_0100',[1]},
                  {'F_01_0090',["3"]},
                  {'F_01_0080',[]},
                  {'F_01_0070',[9999]},
                  {'F_01_0060',[{era,0},{year,[]},{month,[]}]},
                  {'F_01_0050',[]},
                  {'F_01_0040',[]},
                  {'F_01_0030',[]},
                  {'F_01_0020',<<>>},
                  {'F_01_0010',<<"4 - 8">>}]}}],
              [{"eval_data_11",
                {<<"prvl_mobable_asset_0000_h200401">>,
                 [{'F_01_0100',[]},
                  {'F_01_0090',["2"]},
                  {'F_01_0080',[]},
                  {'F_01_0070',[22222]},
                  {'F_01_0060',[{era,0},{year,[]},{month,[]}]},
                  {'F_01_0050',[]},
                  {'F_01_0040',[]},
                  {'F_01_0030',[]},
                  {'F_01_0020',<<>>},
                  {'F_01_0010',<<"4 - 1">>}]}}]],
    merge_set(Eval_set).

OTHER TIPS

@trex:

FormList = [[{EVAL_SEQ_1, {FORMNAME, ListDataToConcat1}}], [{EVAL_SEQ_2, {FORMNAME, ListDataToConcat2}}], ....]

You will need to get a separate the list which has common form names as <<"prvl_mobable_asset_0000_h200401">>

{MobableList, EvalDataList} = lists:partition(fun([{EVAL_SEQ, {FORMNAME, ListData}}]) -> 
            FORMNAME == <<"prvl_mobable_asset_0000_h200401">>
         end, FormList),

Then, Get a separate Tuple of Form sequences and Lists. To separate them

{EvalSeq, MergingList} = lists:foldl(fun(X, {EvalNames, OutList}) -> 
                [{EVAL_SEQ, {FORMNAME, ListData}}] = X,
                {[EVAL_SEQ|EvalNames], [ListData|OutList]}
             end, {[], []}, MobableList),

Hence, you will get the new tuple as :

{[EVAL_SEQ_1, EVAL_SEQ_2, EVAL_SEQ_3, ...], [ListDataToConcat1, ListDataToConcat2, ListDataToConcat3,...]}

I'm not sure which sequence Number you want as you havn't mentioned it clearly, Here is the way you can get the minimum Sequence Number. Evalsequence = lists:min(EvalSeq),

Now merge your code using merge function as shown below or you can refer merging inner list Merge inner lists of a list erlang:

    MergedList = merge(MergingList),

And finally a separate list as:

[{Evalsequence, {<<"prvl_mobable_asset_0000_h200401">>, MergedList}}].


merge(ListOfLists) ->
        Combined = lists:append(ListOfLists),
        Fun      = fun(Key) -> {Key,proplists:get_all_values(Key,Combined)} end,
        lists:map(Fun,proplists:get_keys(Combined)).
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top