我有一个类对象数组,如下所示,thisRate
首先设置为None
:
class Person(object):
def __init__(self, id, name):
self.id = id
self.name = name
self.thisRate= None
我将大约21K Person
个对象加载到一个数组中,name
没有排序。
然后我从一个文件中加载了另一个数组,该文件包含thisRate
的数据,其中约有13K,name
也没有排序:
person_data = []
# read from file
row['name'] = 'Peter'
row['thisRate'] = '0.12334'
person_data.append(row)
现在有了这两组数组,当它们之间匹配name
时,我会将thisRate
中的person_data
分配到Person.thisRate
。
我正在做的是循环是这样的:
for person in persons:
data = None
try:
data = next(personData for personData in person_data
if personData['name'] == person.name)
except StopIteration:
print("No rate for this person: {}".format(person.name))
if data:
person.thisRate = float( data['thisRate'] )
此循环
data = next(personData for personData in person_data
if personData['name'] == person.name)
运行正常,使用Python 2.7.13在我的机器上使用21秒。
我的问题是,有没有更快或更好的方法来实现我拥有的2个数组相同的东西?
答案 0 :(得分:4)
是。制作从name
到thisRate
的词典:
nd = {}
with open(<whatever>) as f:
reader = csv.DictReader(<whatever>):
for row in reader:
nd[row['name']] = row['thisRate']
现在,使用此词典对Person
列表进行一次传递:
for person in persons:
thisRate = nd.get(person.name, None)
person.thisRate = thisRate
if thisRate is None:
print("No rate for this person: {}".format(person.name))
字典有.get
方法,允许您在密钥不在dict
时提供默认值。我使用None
(实际上是默认的默认值),但你可以使用你想要的任何东西。
这是线性时间解决方案。你的解决方案是二次时间,因为你基本上是这样做的:
for person in persons:
for data in person_data:
if data['name'] == person.name:
person.thisRate = data['thisRate']
break
else:
print("No rate for this person: {}".format(person.name))
只是以一种方式掩盖了生成器表达式中基本上嵌套的for循环(对于生成器表达式来说不是一个很好的用例),你应该刚开始使用for循环,然后你不要# 39; t必须处理try-catch
和StopIteration