Sum positive elements of a list efficiently?

There are many ways to sum positive elements of a list such as, e.g.,

In[1]:= list = RandomReal[{-10, 10}, 1000000];

In[2]:= tList = {
  Plus @@ Map[If[# < 0, 0, #] &, list] // AbsoluteTiming,
  Total@Map[If[# < 0, 0, #] &, list] // AbsoluteTiming,
  Total[list /. x_ /; x < 0 -> 0] // AbsoluteTiming
  }

Out[2]= {{2.51129, 2.49923*10^6}, {1.93032, 2.49923*10^6}, {1.6144, 2.49923*10^6}}

In[3]:= BarChart@tList[[All, 1]]

Can you recommend a code better than above ones?

Total[Clip[list, {0, ?}]] is pretty quick.

In[4]:= tList = {Plus @@ Map[If[# < 0, 0, #] &, list] //
AbsoluteTiming,
Total@Map[If[# < 0, 0, #] &, list] // AbsoluteTiming,
Total[list /. x_ /; x < 0 → 0] // AbsoluteTiming,
Plus @@ Select[list, # > 0 &] // AbsoluteTiming }

Out[4]= {{0.942527, 2.49442*10^6}, {0.977524, 
  2.49442*10^6}, {0.778662, 2.49442*10^6}, {0.595495, 2.49442*10^6}}

Fantastic! Thanks a lot! You are magician!

Thanks!

In[6]:= list = RandomReal[{-10, 10}, 1000000];

In[10]:= tList = {
Plus @@ Map[If[# < 0, 0, #] &, list] // AbsoluteTiming,
Total@Map[If[# < 0, 0, #] &, list] // AbsoluteTiming,
Total[list /. x_ /; x < 0 -> 0] // AbsoluteTiming,
Plus @@ Select[list, # > 0 &] // AbsoluteTiming,
Total[Clip[list, {0, \[Infinity]}]] // AbsoluteTiming
}

Out[10]= {{1.76125, 2.49895*10^6}, {1.78087, 2.49895*10^6}, {1.42525,  2.49895*10^6},
{1.07893, 2.49895*10^6}, {0.0146056, 2.49895*10^6}}

In[11]:= BarChart@tList[[All, 1]]

Unbelievable fast!

How about

Total[Clip[list, {0, Infinity}]]

Yes, it is the fastest! It is the lowest bar in the precedent BarChart!

The function Clip[] is useful for multiplication, too…

In[1]:= list = RandomReal[{-10, 10}, 1000000];

In[6]:= tList = {
  Times @@ Map[If[# <= 0, 1, #] &, list] // AbsoluteTiming,
  Times @@ Select[list, # > 0 &] // AbsoluteTiming,
  Times @@ Clip[list, {0, \[Infinity]}, {1, \[Infinity]}] // AbsoluteTiming
  }

Out[6]= {{1.75065, 5.286174502515*10^282473}, {1.06879, 
  5.286174502515*10^282473}, {0.268463, 5.286174502515*10^282473}}

But, what about the case when the list contains not only numerical elements? Can be Clip[] used?

Then how do you know if they’re positive? How do you wish them to be dealt with?

I just wanted to reply this, Clip is the way to do this!

In the next release a new function will arrive that will cut this time in half (compared to Clip).

Another approach is:

AbsoluteTiming[pcf = Piecewise[{{x, x > 0}, {0, True}}]; Total[pcf /@ list];]

But it is slower (at least on my computer).

It was a generic question, meaning that we need another approach… May be based on piece-wise functions…

That wasn’t an answer to my question. :slight_smile: If you have a list like {1, 2, x, -1, -4}, should x be added to the sum, or removed from the list before summing? Same question for {1, 2, I, -1, -4}.

I’d have done it this way: pcf = Function[x, Piecewise[{{x, x > 0}}, 0], Listable]; Total[pcf[tst]]

@Sander The code contains errors! Try it on a small list!

After J.M. improvement

In[32]:= list = RandomReal[{-10, 10}, 1000000];

In[33]:= tList = {
  Plus @@ Map[If[# < 0, 0, #] &, list] // AbsoluteTiming,
  Total@Map[If[# < 0, 0, #] &, list] // AbsoluteTiming,
  Total[list /. x_ /; x < 0 -> 0] // AbsoluteTiming,
  Plus @@ Select[list, # > 0 &] // AbsoluteTiming,
  Total[Clip[list, {0, \[Infinity]}]] // AbsoluteTiming,
  AbsoluteTiming[
   pcf = Function[x, Piecewise[{{x, x > 0}}, 0], Listable]; 
   Total[pcf[list]]]
  }

Out[33]= {{1.71495, 2.50376*10^6}, {1.70818, 2.50376*10^6}, {1.3847, 
  2.50376*10^6}, {1.03566, 2.50376*10^6}, {0.0151026, 
  2.50376*10^6}, {3.1214, 2.50376*10^6}}

In[34]:= BarChart@tList[[All, 1]]

Removed! List may contains elements of different types: chars, images and so on. But we want to sum only numbers. Ok. Positive ones! List may not contains numbers! In such case the result must be clear - that list doesn’t contain numbers!

It’s very impressive for me!

And what about the second list I gave? Complex numbers like I are neither positive nor negative.

We can examine it as special case, i.e.in our case such numbers are not summed.

I believe I’ve seen that, and I have to agree. But let’s not spoil things for other people. :wink: