<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:΢ź
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>Hi Jesper, <div><br></div><div>  Thanks a lot! I'll dig into it.</div><div><br></div><div>Best regards</div><div>Zhiqian<br><br><div><hr id="stopSpelling">From: jesper.louis.andersen@gmail.com<br>Date: Mon, 23 Nov 2015 22:22:55 +0100<br>Subject: Re: [erlang-questions] Update with complicated data structure<br>To: on-your-mark@hotmail.com<br>CC: erlang-questions@erlang.org<br><br><div dir="ltr"><div class="ecxgmail_extra"><br><div class="ecxgmail_quote">On Mon, Nov 23, 2015 at 11:06 AM, YuanZhiqian <span dir="ltr"><<a href="mailto:on-your-mark@hotmail.com" target="_blank">on-your-mark@hotmail.com</a>></span> wrote:<br><blockquote class="ecxgmail_quote" style="border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex;">Sorry to bother you again... I am totally a green hand in Erlang :(</blockquote></div><div class="ecxgmail_extra"><br></div>Suppose for the moment you are willing to use a map to store all your records. Then we can simplify the code quite a lot. List-representations are best used if you often process all of the the elements in the list, or you can use any element of the list, particularly the first one. If you are pin-pointing a specific entry, the map is a far better data structure. First a module definition:</div><div class="ecxgmail_extra"><br><div class="ecxgmail_extra">-module(z).</div><div class="ecxgmail_extra">-export([cal_win_notice/2]).</div><div class="ecxgmail_extra"><br></div><div class="ecxgmail_extra">Next, lets hack up a couple of records to match what is going on in your code:</div><div class="ecxgmail_extra"><br></div><div class="ecxgmail_extra">-record(state, {</div><div class="ecxgmail_extra">        '...',</div><div class="ecxgmail_extra">        companies,</div><div class="ecxgmail_extra">        campaigns</div><div class="ecxgmail_extra">}).</div><div class="ecxgmail_extra"><br></div><div class="ecxgmail_extra">-record(company_info, {</div><div class="ecxgmail_extra">        id,</div><div class="ecxgmail_extra">        budget,</div><div class="ecxgmail_extra">        consumption,</div><div class="ecxgmail_extra">        campaigns</div><div class="ecxgmail_extra">}).</div><div class="ecxgmail_extra"><br></div><div class="ecxgmail_extra">The mapply/3 function here tries to apply F to the map value given by the key ID. If no such ID exists, it leaves the map alone.</div><div class="ecxgmail_extra"><br></div><div class="ecxgmail_extra">mapply(F, ID, Map) -></div><div class="ecxgmail_extra">    case maps:get(ID, Map, undefined) of</div><div class="ecxgmail_extra">        undefined -> Map;</div><div class="ecxgmail_extra">        T -> Map#{ ID := F(T) }</div><div class="ecxgmail_extra">    end.</div><div class="ecxgmail_extra"><br></div><div class="ecxgmail_extra">Now, we can use this function. Make an F which does what we want. Then apply it. We can check if any change were made to the map by matching on the unchanged map. Otherwise, the map has been changed, and we can update the map with the new one.</div><div class="ecxgmail_extra"><br></div><div class="ecxgmail_extra">cal_win_notice({CoID, _Ca, _AdGrp, Price, _Cur}, #state { companies = Cos } = State) -></div><div class="ecxgmail_extra">    F = fun(#company_info{ consumption = Cons } = X) -> X#company_info{ consumption = Cons + Price } end,</div><div class="ecxgmail_extra">    case mapply(F, CoID, Cos) of</div><div class="ecxgmail_extra">        Cos -> {not_found, State}; %% Unchanged map</div><div class="ecxgmail_extra">        Changed -> {ok, State#state { companies = Changed }}</div><div class="ecxgmail_extra">    end.</div><div><br></div><div>Want to make two changes?</div><div><br></div><div>G = fun(#company_info { consumption = Cons } = X) -> X#company_info { consumption = Cons - Price } end,</div><div><br></div><div>compose(F, G) -></div><div>    fun(X) -> G(F(X)) end.</div><div><br></div><div>then mapply(compose(F, G), CoID, Cos) ...</div><div><br></div><div><br></div><br clear="all"><div><br></div>-- <br><div class="ecxgmail_signature">J.</div>
</div></div></div></div>                                          </div></body>
</html>