another solution might be to simply use nub on pairs, after zipping the two lists. this of course assumes that the mapping between values is consistent.<div><br></div><div><font class="Apple-style-span" face="'courier new', monospace">q = map snd $ nub $ zip l m<br>
</font><br><div class="gmail_quote">On 12 September 2010 13:39, Jürgen Doser <span dir="ltr"><<a href="mailto:jurgen.doser@gmail.com">jurgen.doser@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
El dom, 12-09-2010 a las 13:57 +0200, Lorenzo Isella escribió:<br>
<div class="im">> Dear All,<br>
> First of all, thanks to the whole list for their help.<br>
> I am still struggling with things I used to be able to do quite easily<br>
> (though maybe not efficiently) with other languages. I still have to get<br>
> used to the immutable nature of lists and the absence of for loops.<br>
> Let us say you have two lists<br>
><br>
> l = [1,1,1,1,2,2,2,2,2,2,2,3,3,5,6,7] (already sorted)<br>
><br>
> and a list of corresponding values for every entry in l<br>
><br>
> m= [2,2,2,2,4,4,4,4,6,6,4,4,4,10,12,14].<br>
> Also consider the list of the unique values in l<br>
><br>
> l_un = nub l<br>
><br>
> Now, what I would like to do is to get a third list, let us call it q,<br>
> such that its length is equal to the length of l_un.<br>
> On top of that, its i-th entry should be the sum of the entries of m<br>
> corresponding to the i-th values of l_un.<br>
> To fix the ideas, q should be<br>
><br>
> q = [8,32, 8,10,12,14] .<br>
> How would you do that?<br>
<br>
</div>First, we build a list that has the wanted correspondence between m and<br>
l. The function 'zip' pairs the i-th element of l with the i-th element<br>
of m:<br>
<br>
Prelude Data.List Data.Function> zip l m<br>
[(1,2),(1,2),(1,2),(1,2),(2,4),(2,4),(2,4),(2,4),(2,6),(2,6),(2,4),(3,4),(3,4),(5,10),(6,12),(7,14)]<br>
<br>
then, we group by the value of the entry in l. The function 'groupBy'<br>
works just like group, but it allows to specify the predicate by which<br>
to group elements, instead of simply using equality (group === groupBy<br>
(==)). Here, we want to group pairs if their first component is equal,<br>
i.e., our grouping predicate is<br>
<br>
\(a,b) (c,d) -> a == c<br>
<br>
or<br>
<br>
\x y -> fst x == fst y<br>
<br>
or<br>
<br>
(==) `on` fst<br>
<br>
this gives:<br>
<br>
Prelude Data.List Data.Function> groupBy ((==) `on` fst) $ zip l m<br>
[[(1,2),(1,2),(1,2),(1,2)],[(2,4),(2,4),(2,4),(2,4),(2,6),(2,6),(2,4)],[(3,4),(3,4)],[(5,10)],[(6,12)],[(7,14)]]<br>
<br>
now, we can forget about the l-values. we are only interested in the<br>
values of the m list. To do this, we extract the second component of<br>
each pair, using the function snd. As these pairs are elements of list,<br>
and we want to extract the second component of all of them, we have to<br>
'map' the function 'snd' over these lists. Now, these lists are<br>
themselves elements of our list, so we have to 'map' the function 'map<br>
snd' over it:<br>
<br>
Prelude Data.List Data.Function> map (map snd) . groupBy ((==) `on` fst) $ zip l m<br>
[[2,2,2,2],[4,4,4,4,6,6,4],[4,4],[10],[12],[14]]<br>
<br>
Finally, we only have to sum up the values in these lists. The function<br>
'sum' sums up the values in a list, and as we want to do this for all<br>
the lists in our list, we simply map it:<br>
<br>
Prelude Data.List Data.Function> map sum . map (map snd) . groupBy ((==) `on` fst) $ zip l m<br>
<div class="im">[8,32,8,10,12,14]<br>
<br>
<br>
</div>The last line can be slightly simplified, because<br>
<br>
map f . map g === map (f . g)<br>
<br>
to<br>
<br>
map (sum . map snd) . groupBy ((==) `on` fst) $ zip l m<br>
<font color="#888888"><br>
<br>
Jürgen<br>
</font><div><div></div><div class="h5"><br>
_______________________________________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/beginners" target="_blank">http://www.haskell.org/mailman/listinfo/beginners</a><br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br>Ozgur Akgun<br>
</div>