成员

时间:2015-12-07 21:51:02

标签: python

我试图找到一种更加pythonic的方式来做这个条件总和:

...
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 >= start and s.TimeStamp < end]
   if len(filtered) > 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 >= start and s.TimeStamp < end]
   if len(filtered) > 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 >= start and s.TimeStamp < end]
   if len(filtered) > 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 >= start and s.TimeStamp < end]
   if len(filtered) > 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 >= start and s.TimeStamp < end]
   if len(filtered) > 0:
      return sum(filtered)
   else:
      return 0

因此,反向迭代,从第2个到最后一个,并获取相对于事件数据的源数据的聚合。不要获得第一个值的聚合。

events {}和source {}都是.NET类型的字典,如下所示:

.Variant 
.TimeStamp

.Variant结构几乎是旧的VB Variant类型。

对于事件中的每个事件,我想要查找源中的所有值&gt; =事件的时间戳,并且&lt;下一个事件的时间戳。

我上面的详细代码有效,但它似乎缺乏与python关联的某种优雅,就像我正在努力做到这一点。

注意:这是嵌入式IronPython环境,因此我无法导入numpy或任何其他模块。我只能使用IP2.6运行时。此外,我无法弹出.NET程序集,因此我的代码必须作为脚本工作。我在这里发布了这个,因为我没有看到除了环境之外它是特定的IronPython。我可以部署脚本(作为模型中对象的字符串属性),但不能部署程序集。我所拥有的只是直接的文本代码。

我打破了开始和结束变量,因为似乎理解语法并不理解嵌入的方括号。

有多糟糕?有没有办法用发电机做到这一点?他们都会过滤相同的,所以如果我可以用

返回一个对象
.min
.max
.sum
.total
.avg

那会让我很开心。特别是如果它摆脱了冗余代码。

2 个答案:

答案 0 :(得分:0)

好的,facepalm。也许我太努力了。如果我这样做:

for i in xrange(len(event_vqts)-2, 0, -1):
   start = event_vqts[i].TimeStamp
   end = event_vqts[i + 1].TimeStamp
   times[start] = end
   durations[start] = (end - start).TotalMilliseconds / float(1000)      
   filtered = [s.Variant.Double for s in source_vqts if s.TimeStamp >= start and s.TimeStamp < end]
   count = len(filtered)
   if count > 0:
      total = float(filtered[-1] - filtered[0])
      if total < 0:
         total = float((filtered[-1] + rollover) - filtered[0])
      totals[start] = total
      counts[start] = count
      mins[start] = min(filtered)
      maxs[start] = max(filtered)
      avgs[start] = sum(filtered) / float(count)
      sums[start] = sum(filtered)
      stds[start] = std(filtered)
      starting_values[start] = filtered[0]
      ending_values[start] = filtered[-1]
   else:
      totals[start] = 0
      counts[start] = 0
      mins[start] = 0
      maxs[start] = 0
      avgs[start] = 0
      sums[start] = 0
      stds[start] = 0
      starting_values[start] = 0
      ending_values[start] = 0

它似乎满足了我的需求。

虽然现在我想知道发电机对于更大的设备是否更具性能?我将研究@adam-smith的解决方案,因为它看起来很干净。

答案 1 :(得分:0)

考虑将整个事物包装在一个知道如何过滤自身的对象中。

class EventInterface(list):
    # pass in the `source` list
    def filter(event, index):  # returns a generator
        start = event[index].TimeStamp
        end = event[index+1].TimeStamp
        return (s for s in self if start <= s.TimeStamp < end)

sources = EventInterface(sourceVqts)

for i in range(len(eventVqts)-2, 0, -1):
    filtered = map(attrgetter('Variant.Double'), sources.filter(eventVqts, i))

然后你可以用结果做你喜欢的事。

def avg(sources):
    return float(sum(sources)) / len(sources)

def total(sources):
    return sources[-1] - sources[0]

for i in range(len(eventVqts)-2, 0, -1):
    filtered = map(attrgetter('Variant.Double'), sources.filter(eventQvts, i))
    the_sum = sum(filtered)
    the_avg = avg(filtered)
    the_total = total(filtered)
    # etc....