<html><head></head><body>You can improve it by removing the last clause<br>
F({section, _, []}) -> false<br>
<br><br><div class="gmail_quote">On 14 July 2018 22:41:34 GMT+10:00, Stanislav Ledenev <s.ledenev@gmail.com> wrote:<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<pre class="k9mail">Mikael, thank you very much for a hint!<br><br>After some reasoning I came up to this solution:<br><br>filter(List, Search) -><br>     F = fun F({policy, I, _}) -> lists:member(I, Search);<br>             F({section, SI, C}) -><br>                 R = lists:filtermap(F, C),<br>                 case R of<br>                     [] -> false;<br>                     _ -> {true, {section, SI, R}}<br>                 end;<br>             F({section, _, []}) -> false<br>         end,<br>     lists:filtermap(F, List).<br><br>It doesn't seem that it could be improved more.<br><br>On 14.07.2018 11:54, Mikael Pettersson wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;"> On Fri, Jul 13, 2018 at 3:25 PM, Stanislav Ledenev <s.ledenev@gmail.com> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;"> Hello,<br><br> I am new to Erlang and functional programming (1-1.5 months) and have task:<br><br> 1. Suppose we have hierarchical tree-like data structure:<br> L = [<br> {section, "id1", [<br> {section, "id1.1", [<br> {policy, "p1", "v1"},<br> {policy, "p2", "v2"}<br> ]},<br> {section, "id1.2", [<br> ]}<br> ]},<br> {section, "id2", [<br> {policy, "p3", "v3"}<br> ] },<br> {section, "id3", [<br> ] }<br> ]<br><br> 2. List of some "section"'s with children elements any of which could be<br> another "section" with children or "policy" with name and value.<br><br> 3. Also we have another list which contains identifiers of policies:<br> F = ["p1", "p3"].<br> 4. Now I need to write a function which takes lists L, F and returns list L2<br> such as L2 contains only those "section"'s which has "policies" wich Id<br> equals to those in F. Empty sections must be removed.<br><br> For lists L and F result should be:<br> L2 = [<br> {section, "id1", [<br> {section, "id1.1", [<br> {policy, "p1", "v1"},<br> ]},<br> ]},<br> {section, "id2", [<br> {policy, "p3", "v3"}<br> ] },<br> ]<br><br> 5. I have solution (please see below) but it seems to me not as good as<br> it can be and even little weird. I am sure that it could be improved<br> and done in proper way.<br> If anyone could give me any glimpse or advice I would appreciate.<br><br> Source:<br><hr><br> main() -><br>      L = [<br>              {section, "id1", [<br>                  {section, "id1.1", [<br>                      {policy, "p1", "v1"},<br>                      {policy, "p2", "v2"}<br>                  ]},<br>                  {section, "id1.2", [<br>                  ]}<br>              ]},<br>              {section, "id2", [<br>                  {policy, "p3", "v3"}<br>              ] },<br>              {section, "id3", [<br>              ] }<br>          ],<br>      %filter(L, ["p1", "p3"]).<br>      filter(L, ["p3"]).<br><br> filter([H | T], Search) -><br>      lists:flatten([filter(H, Search, []) | filter(T, Search, [])]).<br><br> filter({section, I, C}, Search, _Acc) -><br>      NewC = filter(C, Search, []),<br>      case NewC of<br>          [] -> [];<br>          _ -> {section, I, NewC}<br>      end;<br><br> filter([{section, I, C} | T], Search, Acc) -><br>      NewC = filter(C, Search, []),<br>      case NewC of<br>          [] -> filter(T, Search, Acc);<br>          _ -> filter(T, Search, [{section, I, NewC} | Acc])<br>      end;<br><br> filter([{policy, I, V} | T], Search, Acc) -><br>      case lists:member(I, Search) of<br>          true -> filter(T, Search, [{policy, I, V} | Acc]);<br>          false -> filter(T, Search, Acc)<br>      end;<br> filter([], _S, Acc) -> Acc.<br></blockquote> Just some high-level comments.<br><br> - Your data is clearly layered (there are items which can be policies<br> or sections, and sections in turn contain lists of items), but your<br> filtering code conflates these and in turn gets confused as to what<br> it's processing, hence the large number of cases in filter/3.  Also,<br> your code would crash if the top-level lists starts with a policy, but<br> accepts it elsewhere, which smells like a bug.<br> - You roll your own logic for reassembling the filtered-out fragments,<br> which gets unnecessarily fiddly, and in this case I think wrong (you<br> reorder items).<br> - Using lists:filtermap/2 would greatly simplify your code.<br></blockquote><br><hr><br>erlang-questions mailing list<br>erlang-questions@erlang.org<br><a href="http://erlang.org/mailman/listinfo/erlang-questions">http://erlang.org/mailman/listinfo/erlang-questions</a><br></pre></blockquote></div><br>
-- <br>
Kind regards,<br>
Dmitry Belyaev</body></html>