2 回答
TA贡献1829条经验 获得超6个赞
这是您的解决方案......
def cross(listMaster, listSlave, criteria="email"):
if criteria == "email":
returnUnique = listMaster[:] # create a copy of the master list
emails_in_master = set()
for item in listMaster:
emails_in_master.add(item[2]) # add the master emails to the set
for item in listSlave:
if item[2] in emails_in_master:
returnUnique.append(item)
return returnUnique
您的算法是 O(n^2),因为您正在遍历一个列表,然后在每次迭代上述内容时搜索另一个列表。这会导致指数运行时间,这基本上是您可以获得的最糟糕的结果。您需要尝试使算法具有线性复杂度,以便获得不错的运行时间。
你的算法基本上如下:
loop for n: # this costs n
loop for n: # this costs n for each of the n's above
add an item or continue # so total, this is O(n * n)
你想要的是以下内容:
loop for n: # this costs n
build a lookup
loop for n: # this costs n
add item if in lookup or continue # so total, this is O(n)
我在本地机器上将测试数据生成到 CSV 中。这是我创建 CSV 的方式...
>>> import csv
>>> from faker import Faker
>>> fake = Faker()
>>> with open('masters.csv', 'wb') as csvfile:
... writer = csv.writer(csvfile, delimiter=',', quotechar='"')
... for i in range(20000):
... writer.writerow([fake.name(), fake.address(), fake.email(), fake.job(), fake.ssn()])
...
>>> with open('slaves.csv', 'wb') as csvfile:
... writer = csv.writer(csvfile, delimiter=',', quotechar='"')
... for i in range(20000):
... writer.writerow([fake.name(), fake.address(), fake.email(), fake.job(), fake.ssn()])
...
一旦生成了这些(注意每个文件有 20k,因为生成 200 万的时间太长了),我构建了以下测试套件来比较不同的方法......
import csv
import unittest
email = lambda l: l[2]
class TestListComparison(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.masters = []
cls.slaves = []
with open('masters.csv', 'rb') as master_csv:
reader = csv.reader(master_csv, delimiter=',', quotechar='"')
cls.masters = list(reader)
with open('slaves.csv', 'rb') as slave_csv:
reader = csv.reader(slave_csv, delimiter=',', quotechar='"')
cls.slaves = list(reader)
def test_make_sure_lists_are_well_formed(self):
self.assertEqual(len(self.masters), len(self.slaves))
self.assertEqual(len(self.masters), 20000)
def test_list_combination_original(self):
emailListSlave = []
returnUnique = []
for item in self.slaves:
emailListSlave.append(email(item))
for no, item in enumerate(self.masters): # O(n)
if email(item) not in self.slaves: # O(n)
returnUnique.append(item) # O(1)
# Total complexity: O(n * n * 1) => O(n^2)
def test_list_combination_using_lookup(self):
lookup = set()
returnUnique = self.masters[:] # create a copy of masters list
for master in self.masters: # loop over the master list O(n)
lookup.add(email(master)) # add the email to the set O(1)
for slave in self.slaves: # loop over the list again O(n)
if email(slave) in lookup: # check the lookup O(1)
returnUnique.append(slave) # add the item to the list O(1)
# Total complexity: O(n + n) => O(2n) => O(n)
下面是运行结果:
请注意,查找测试花费了大约 15 毫秒,而原始算法花费了大约 14 秒。那快了几个数量级。
添加回答
举报