Python 里面大,里面大。我怎样才能减少时间?
我有两个列表(“ID”和“付款”)。ID的长度为50000,工资的长度为650000 IDS是一个ID列表,如[1,2,3,4,5,6…],付款列表是一个包含IDS所做的所有付款的列表,如[[1,50]、[1100]、[1,60]、[2,50]、[2,80]、[2,50]、…] 为了知道每个ID总共支付了多少钱,我在另一个for循环中做了一个for循环,如下所示:Python 里面大,里面大。我怎样才能减少时间?,python,loops,for-loop,logic,Python,Loops,For Loop,Logic,我有两个列表(“ID”和“付款”)。ID的长度为50000,工资的长度为650000 IDS是一个ID列表,如[1,2,3,4,5,6…],付款列表是一个包含IDS所做的所有付款的列表,如[[1,50]、[1100]、[1,60]、[2,50]、[2,80]、[2,50]、…] 为了知道每个ID总共支付了多少钱,我在另一个for循环中做了一个for循环,如下所示: for x in IDS: total = 0 for i in xrange(0,len(Pay)):
for x in IDS:
total = 0
for i in xrange(0,len(Pay)):
if x == Pay[i][0]:
total += Pay[i][1]
print x + str(total)
但这需要花费很多时间来处理!
我试着把工资分成10份,但还是花了太长时间。
有人知道我该如何改进这个操作吗
谢谢大家! 您可以使用
集合。计数器:
>>> from collections import Counter
>>> pay = [ [1,50], [1,100], [1,60], [2,50], [2,80], [2,50]]
>>> c = Counter()
>>> for idx, amt in pay:
c[idx] += amt
...
>>> c
Counter({1: 210, 2: 180})
您可以使用集合。计数器
:
>>> from collections import Counter
>>> pay = [ [1,50], [1,100], [1,60], [2,50], [2,80], [2,50]]
>>> c = Counter()
>>> for idx, amt in pay:
c[idx] += amt
...
>>> c
Counter({1: 210, 2: 180})
如果collections.Counter
对您不起作用,比如说,如果您使用的是不同的Python版本,那么将您的薪资列表转换为字典将具有相同的效果
totals = {}
for id, amount in pay:
totals[id] = totals.setdefault(id, 0) + amount
如付款日期[1,502013-09-01],我必须对
仅限日期大于“2013-01-01”的值
然后这样做:
import datetime
base_date = datetime.datetime.strptime('2013-01-01', '%Y-%m-%d').date()
totals = {}
for idx, amount, pay_date in pay:
if datetime.datetime.strptime(pay_date, '%Y-%m-%d').date() > base_date:
totals[idx] = totals.setdefault(id, 0) + amount
如果collections.Counter
对您不起作用,比如说,如果您使用的是不同的Python版本,那么将您的薪资列表转换为字典将具有相同的效果
totals = {}
for id, amount in pay:
totals[id] = totals.setdefault(id, 0) + amount
如付款日期[1,502013-09-01],我必须对
仅限日期大于“2013-01-01”的值
然后这样做:
import datetime
base_date = datetime.datetime.strptime('2013-01-01', '%Y-%m-%d').date()
totals = {}
for idx, amount, pay_date in pay:
if datetime.datetime.strptime(pay_date, '%Y-%m-%d').date() > base_date:
totals[idx] = totals.setdefault(id, 0) + amount
您只需要迭代Pay
一次(而不是50000次!)。通过哈希运算,您可以大大加快计算速度:
totals = dict(map(lambda id: (id,0), IDS))
for L in Pay:
if L[0] in totals:
totals[L[0]] = totals[L[0]] + L[1]
for (id, total) in totals.iteritems():
print "id: %s, total: %d"%(id, total)
您只需要迭代Pay
一次(而不是50000次!)。通过哈希运算,您可以大大加快计算速度:
totals = dict(map(lambda id: (id,0), IDS))
for L in Pay:
if L[0] in totals:
totals[L[0]] = totals[L[0]] + L[1]
for (id, total) in totals.iteritems():
print "id: %s, total: %d"%(id, total)
好的,事实是你有两个很长的列表。与其讨论使用什么库,不如讨论一个更好的算法
IDs自然应该包含唯一的整数(我猜),而Pay是(id,payment)的元组
现在想想你的清单是从哪里来的。有两种可能性:
从文件中读取
从一些数据库,比如MySQL
如果是选项1,则应执行以下操作:
from collections import defaultdict
totals = defaultdict(someObj_factory)
[totals[int(line.split[0])].accumulate(someObj_factory(line.split()[1]))
for line in paymentFile]
首先,你不需要ID作为一个独立的列表,因为你有他们在支付
其次,它节省了阅读时间
第三,对于脚本语言,列表理解节省了解释时间
第四,这是健壮的,因为您可以添加任何想要的对象,比如日期或元组
如果是选项2,则在数据库中进行计数--
另一个选项是将这些数据插入数据库,并在其中进行计数。MySQL等都是为这种任务而设计的。你会惊讶于它的效率。更多信息:好的,事实是你有两个很长的列表。与其讨论使用什么库,不如讨论一个更好的算法
IDs自然应该包含唯一的整数(我猜),而Pay是(id,payment)的元组
现在想想你的清单是从哪里来的。有两种可能性:
从文件中读取
从一些数据库,比如MySQL
如果是选项1,则应执行以下操作:
from collections import defaultdict
totals = defaultdict(someObj_factory)
[totals[int(line.split[0])].accumulate(someObj_factory(line.split()[1]))
for line in paymentFile]
首先,你不需要ID作为一个独立的列表,因为你有他们在支付
其次,它节省了阅读时间
第三,对于脚本语言,列表理解节省了解释时间
第四,这是健壮的,因为您可以添加任何想要的对象,比如日期或元组
如果是选项2,则在数据库中进行计数--
另一个选项是将这些数据插入数据库,并在其中进行计数。MySQL等都是为这种任务而设计的。你会惊讶于它的效率。更多信息:使用dict进行支付{IDS:IDSmult}~O(1)代替O(n)用dict来支付怎么样?比如Pay={1:[50100,60]},2:[50,80,50,…。如果使用dict,你也可以删除ID。使用dict进行Pay{IDS:IDSmult}。~O(1)而不是O(n)如何使用dict进行支付?比如Pay={1:[50100,60]},2:[50,80,50,…。如果使用dict,你也可以删除ID。很好,不知道收款!但是如果“Pay”列表中有更多信息,如付款日期[1,502013-09-01],我只需对大于'2013-01-01'的日期的值求和?@Antonio只需添加一个if
条件:对于idx,amt,dt in pay:if dt>2013-09-01:c[idx]+=amt
。(别忘了使用datetime.datetime.strtime
将日期字符串转换为datetime对象)@Antonio:如果这对你有效,你应该接受这个解决方案=DNice,不知道收款!但是如果“付款”列表有更多信息,比如付款日期[1,502013-09-01]而且我必须只对大于'2013-01-01'的日期的值求和?@Antonio只需添加一个if
条件:对于idx,amt,dt in pay:if dt>2013-09-01:c[idx]+=amt
(别忘了使用datetime.datetime.strtime
将日期字符串转换为datetime对象)@安东尼奥:如果这对您有效,您应该接受此解决方案=DDon不要使用id
作为变量名。不要使用id
作为变量名。如果Pay[i][0]
for alli
在id
中,那么您可以通过省略包含检查来进一步优化,即如果L[0]总计
。即使您不能散列,这种迭代方式仍然是优越的,因为它可能会最大化缓存命中率。如果Pay[i][0]
for alli
在IDS
中,那么您可以通过省略包含检查来进一步优化,即if L[0]在totals中
。即使您不能散列,这种迭代方式仍然是优越的,因为它可能会最大化缓存命中率。