我有一个类 Person 的对象数组,如下所示,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
匹配时,我将从 person_data
中分配 thisRate
到 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 个数组实现相同的目的?
最佳答案
是的。制作一个从 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 循环,然后你不不必处理 try-catch
和 StopIteration
关于python - 比循环查找数据更快或更好的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43244024/