title: Pythonic conditional sum on member
body: <p>I am trying to find a more pythonic way of doing this conditional sum:</p>
  
  <pre><code>...
  for i in xrange(len(eventVqts)-2, 0, -1):
     events[eventVqts[i].TimeStamp] = total(eventVqts, sourceVqts, i)
     mins[eventVqts[i].TimeStamp] = minx(eventVqts, sourceVqts, i)
     maxs[eventVqts[i].TimeStamp] = maxx(eventVqts, sourceVqts, i)
     avgs[eventVqts[i].TimeStamp] = avgx(eventVqts, sourceVqts, i)
     sums[eventVqts[i].TimeStamp] = sumx(eventVqts, sourceVqts, i)
     times[eventVqts[i].TimeStamp] = eventVqts[i + 1].TimeStamp
     durations[eventVqts[i].TimeStamp] = (eventVqts[i+1].TimeStamp - eventVqts[i].TimeStamp).TotalMilliseconds
  ...
  
  def total(events, source, index):
     start = events[index].TimeStamp
     end = events[index+1].TimeStamp
     filtered = [s.Variant.Double for s in source if s.TimeStamp &gt;= start and s.TimeStamp &lt; end]
     if len(filtered) &gt; 0:
        return filtered[-1] - filtered[0]
     else:
        Log.Error('No filtered records found')
        return 0
  
  def minx(events, source, index):
     start = events[index].TimeStamp
     end = events[index+1].TimeStamp
     filtered = [s.Variant.Double for s in source if s.TimeStamp &gt;= start and s.TimeStamp &lt; end]
     if len(filtered) &gt; 0:
        return min(filtered)
     else:
        return 0
  
  def maxx(events, source, index):
     start = events[index].TimeStamp
     end = events[index+1].TimeStamp
     filtered = [s.Variant.Double for s in source if s.TimeStamp &gt;= start and s.TimeStamp &lt; end]
     if len(filtered) &gt; 0:
        return max(filtered)
     else:
        return 0
  
  def avgx(events, source, index):
     start = events[index].TimeStamp
     end = events[index+1].TimeStamp
     filtered = [s.Variant.Double for s in source if s.TimeStamp &gt;= start and s.TimeStamp &lt; end]
     if len(filtered) &gt; 0:
        return sum(filtered) / float(len(filtered))
     else:
        return 0
  
  def sumx(events, source, index):
     start = events[index].TimeStamp
     end = events[index+1].TimeStamp
     filtered = [s.Variant.Double for s in source if s.TimeStamp &gt;= start and s.TimeStamp &lt; end]
     if len(filtered) &gt; 0:
        return sum(filtered)
     else:
        return 0
  </code></pre>
  
  <p>So, reverse iterate, starting at 2nd to the last, and grab the aggregations of the source data relative to the event data. Don't get the first value's aggregations.</p>
  
  <p>events{} and source{} are both dictionaries of a .NET type which looks like:</p>
  
  <pre><code>.Variant 
  .TimeStamp
  </code></pre>
  
  <p>The .Variant structure is pretty much the old VB Variant type.</p>
  
  <p>For each event in events, I want to find all the values in the sources that are >= the timestamp of the event, and &lt; the timestamp of the next event.</p>
  
  <p>My verbose code above works, but it seems to lack a certain elegance I associate with python, like I am working too hard to do this.</p>
  
  <p>NOTE: this is en embedded IronPython environment, so I can't import numpy or any other modules. I only have the IP2.6 runtime to work with. Also, I can't pop in a .NET assembly, so my code has to work as a script. I posted this here, as I did not see that it was IronPython specific, other than the environment. I can deploy a script (as a string property of an object in the model), but not an assembly. All I have is straight text code to work with.</p>
  
  <p>I broke out the start and end variables because it seemed the comprehension syntax did not appreciate embedded square brackets.</p>
  
  <p>How bad is it? Is there a way to do this using a generator? They would all filter the same, so if I could return an object with</p>
  
  <pre><code>.min
  .max
  .sum
  .total
  .avg
  </code></pre>
  
  <p>That would make me very happy. Especially if it got rid of redundant code.</p>