2

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">>]}]}}]
Raniz
  • 10,882
  • 1
  • 32
  • 64
  • Your expected result has some inconsistancy `{'F_01_0090',[["2"], ["3"]]} different of {'F_01_0010',[[<<"4 - 1">>], <<"4 - 8">>]}` , you should, also clarify if you want duplicated results like `{'F_01_0050',[[], []]}` rather than `{'F_01_0050',[[]]}`, if you want to merge in a single asset all the results, even if they appear in a single one or if the list of keys is always the same in every asset. – Pascal Apr 28 '14 at 13:00
  • @Pascal: Sorry, That was my mistake. Please check now it has been corrected. –  Apr 29 '14 at 05:49

2 Answers2

1

@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)).
Community
  • 1
  • 1
Laxmikant Ratnaparkhi
  • 4,745
  • 5
  • 33
  • 49
1

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).
Pascal
  • 13,977
  • 2
  • 24
  • 32
  • :Your code is very pretty. Thanks for the solution, I have one issue there, I want a lowest eval form number i.e. Result should appear with "eval_data_11". This is happening in above case. But when I used this code in my project, I'm not getting lowest eval form number. Since client level javascript is throwing error. –  Apr 30 '14 at 07:27
  • see modified version in the answer – Pascal Apr 30 '14 at 08:02