按类型有效地对项目进行求和

时间:2017-04-12 18:43:12

标签: python python-3.x iteration list-comprehension

我有一个包含属性{"access_token":"ACCESS_TOKEN","token_type":"bearer","expires_in":2592000,"refresh_token":"REFRESH_TOKEN","scope":"read","uid":100101,"info":{"name":"Mark E. Mark","email":"mark@thefunkybunch.com"}} "Type"的项目列表,我想快速将每个"Time"的时间相加并附加到另一个列表。该列表如下所示:

"Type"

我想做一些像这样的事情:

Items = [{'Name': A, 'Type': 'Run', 'Time': 5},  
          {'Name': B, 'Type': 'Walk', 'Time': 15},  
          {'Name': C, 'Type': 'Drive', 'Time': 2},
          {'Name': D, 'Type': 'Walk', 'Time': 17},  
          {'Name': E, 'Type': 'Run', 'Time': 5}]

Travel_Times=[("Time_Running","Time_Walking","Time_Driving")] Run=0 Walk=0 Drive=0 for I in Items: if I['Type'] == 'Run': Run=Run+I['Time'] elif I['Type'] == 'Walk': Walk=Walk+I['Time'] elif I['Type'] == 'Drive': Drive=Drive+I['Time'] Travel_Times.append((Run,Walk,Drive)) 最终看起来像这样:

Travel_Times

对于列表理解或与print(Travel_Times) [("Time_Running","Time_Walking","Time_Driving") (10,32,2)] 类似的事情,这似乎很容易有效,但我无法弄清楚。我想到的最好的方法是为每个“类型”使用单独的列表推导,但这需要重复遍历列表。我很感激有关如何加快它的任何想法。

由于

7 个答案:

答案 0 :(得分:2)

您可以使用dict来跟踪总时间。使用.get()方法,您可以计算总时间。如果活动的密钥不存在,请将其标记设置为零并从那里开始计数。

items = [{'Name': 'A', 'Type': 'Run', 'Time': 5},  
          {'Name': 'B', 'Type': 'Walk', 'Time': 15},  
          {'Name': 'C', 'Type': 'Drive', 'Time': 2},
          {'Name': 'D', 'Type': 'Walk', 'Time': 17},  
          {'Name': 'E', 'Type': 'Run', 'Time': 5}]

totals = {}

for item in items:
    totals[item['Type']] = totals.get(item['Type'], 0) + item['Time']

for k, v in totals.items():
    print("Time {}ing:\t {} mins".format(k, v))

答案 1 :(得分:2)

您可以使用Counter中的collections以及来自chain的{​​{1}}和repeat

itertools

这个小小的代码段会生成一个from itertools import chain, repeat from collections import Counter from_it = chain.from_iterable res = Counter(from_it(repeat(d['Type'], d['Time']) for d in Items)) 个实例,其中包含以下内容:

Counter

它使用print(res) Counter({'Drive': 2, 'Run': 10, 'Walk': 32}) 显然会在repeat次重复d['Type'],然后使用d['Time']将所有这些内容提供给Counter以进行求和。< / p>

如果您的chain.from_iterable列表包含多个条目,则可以再次使用Items将这些条目链接在一起:

chain.from_iterable

这将为您提供所有嵌套列表中所有类型的总和。

答案 2 :(得分:2)

请注意,案例在Python中非常重要:

  • For不是有效的陈述
  • Travel_timesTravel_Times
  • 不同
  • :
  • 之后没有elif
  • Travel_Times.append(...有一个领先的空间,它会混淆Python
  • items有一个[太多
  • A未定义

话虽如此,Counter对你的例子来说效果很好:

from collections import Counter

time_counter = Counter()

items = [{'Name': 'A', 'Type': 'Run', 'Time': 5},  
          {'Name': 'B', 'Type': 'Walk', 'Time': 15},  
          {'Name': 'C', 'Type': 'Drive', 'Time': 2},
          {'Name': 'D', 'Type': 'Walk', 'Time': 17},  
          {'Name': 'E', 'Type': 'Run', 'Time': 5}]

for item in items:
    time_counter[item['Type']] += item['Time']

print(time_counter)
# Counter({'Walk': 32, 'Run': 10, 'Drive': 2})

获取元组列表:

[tuple(time_counter.keys()), tuple(time_counter.values())]
# [('Run', 'Drive', 'Walk'), (10, 2, 32)]

答案 3 :(得分:1)

您可以reduce使用collections.Counter

# from functools import reduce # Python 3

d = reduce(lambda x, y: x + Counter({y['Type']: y['Time']}), Items, Counter())          
print(d)
# Counter({'Walk': 32, 'Run': 10, 'Drive': 2})

它只是使用相应的Counter值构建Type更新每个Time

答案 4 :(得分:1)

以下是在一行中表达您想要的内容的简要方法。顺便说一句,您的列表Items不需要加倍括号:

>>> Items = [{'Type': 'Run', 'Name': 'A', 'Time': 5}, 
         {'Type': 'Walk', 'Name': 'B', 'Time': 15}, 
         {'Type': 'Drive', 'Name': 'C', 'Time': 2}, 
         {'Type': 'Walk', 'Name': 'D', 'Time': 17}, 
         {'Type': 'Run', 'Name': 'E', 'Time': 5}]
>>> zip(("Time_Running","Time_Walking","Time_Driving"), (sum(d['Time'] for d in Items if d['Type'] == atype) for atype in 'Run Walk Drive'.split()))
[('Time_Running', 10), ('Time_Walking', 32), ('Time_Driving', 2)]

在这里,我将输出标签压缩到一个生成器,该生成器计算您列出的三种运输类型中的每一种的总和。对于您的确切输出,您可以使用:

>>> [("Time_Running","Time_Walking","Time_Driving"), tuple(sum(d['Time'] for d in Items if d['Type'] == atype) for atype in 'Run Walk Drive'.split())]
[('Time_Running', 'Time_Walking', 'Time_Driving'), (10, 32, 2)]

答案 5 :(得分:1)

如果您愿意滥用发生器产生副作用:

from collections import Counter
count = Counter()
# throw away the resulting elements, as .update does the work for us
[_ for _ in (count.update({item['Type']:item['Time']}) for item in items) if _]

>>> count
Counter({'Walk': 32, 'Run': 10, 'Drive': 2})

这可行,因为Counter.update()会返回Noneif None将始终评估False并抛弃该元素。因此,这会产生副作用空列表[]作为唯一的内存开销。 if False同样有效。

答案 6 :(得分:0)

只需使用字典!请注意,在python中,对snake_case使用变量和键是个人的。

travel_times = {'run': 0, 'walk': 0, 'drive': 0}
for item in items:
    action, time = item['type'], item['time']
    travel_times[action] += time