Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it bad to use toList?

Suppose 2 Maps

import qualified Data.Map as M
sparse1, sparse2 :: M.Map Int Float
sparse1 = M.fromList [(1,2.0),(10,3),(12,5),(100,7),(102,11)]
sparse2 = M.fromList [(2,13.0),(11,17),(12,19),(101,23),(102,29)]

How do you define an elegant function

combi :: M.Map Int Float -> M.Map Int Float -> Float

such that combi sparse1 sparse2 returns 414.0 (= 5 * 19 + 11 * 29) because 12 and 102 are the only common keys of the two maps ? There is an elegant (simple and efficient) function with lists since those would be strictly ordered:

combiList xs ys = cL xs ys 0
cL [] _ acc = acc
cL _ [] acc = acc
cL (x@(k,r):xs) (y@(k',r'):ys) acc 
    | k < k'  = cL xs     (y:ys) acc
    | k == k' = cL xs     ys     (acc+r*r')
    | k > k'  = cL (x:xs) ys     acc

But is

combi m1 m2 = combiList (M.toList m1) (M.toList m2)

a good idea knowing the lists are no more used in the rest of the code ? And if not, how would you efficiently write combi without toList ?

like image 283
sauf Avatar asked Oct 05 '10 00:10

sauf


People also ask

Does ToList decrease performance?

ToList , the code calls Enumerable. ToList() which is an extension method that return new List<TSource>(source) . In the corresponding constructor, under the worst circumstance, it goes through the item container and add them one by one into a new container. So its behavior affects little on performance.

Why do we use ToList?

The ToList<TSource>(IEnumerable<TSource>) method forces immediate query evaluation and returns a List<T> that contains the query results. You can append this method to your query in order to obtain a cached copy of the query results. ToArray has similar behavior but returns an array instead of a List<T>.

What is faster ToArray or ToList?

ToArray might do an additional allocation and copy operation such that the buffer will be sized exactly to the number of elements. In order to confirm this the following benchmark is used. The results confirm that ToList is in most cases 10% - 15% faster.

When should I call ToList?

Use ToList before you exit the using block that holds your DataContext . Return a query when the caller is likely/obligated to supply additional filtering criteria which will be used by indexes to reduce # of result rows and/or database IO.


1 Answers

Using fold and intersectWith on the maps is a bit more elegant (and probably faster):

combi :: M.Map Int Float -> M.Map Int Float -> Float
combi x y = M.fold (+) 0 $ M.intersectionWith (*) x y

combi sparse1 sparse2 returns 414.0 as desired.

And if you care about performance, try using Data.IntMap: it should be several times faster than Data.Map here.

like image 198
Travis Brown Avatar answered Sep 20 '22 04:09

Travis Brown