写了两个生成器 agentman,agreement,生成器里面的元素是一个个的 python 字典,每个字典里面都有一个 key 相同,key 对应的 value 也相同,我的需求就是分别遍历两个生成器找出拥有相同 key-value 的字典,然后将这两个字典合并成一个字典。(有没有更好的实现方法,两个 for 循环看起来实在是太丑了)
for i in agreement:
for j in agentman:
if i['agent_name'] == j['agent_name']:
print(dict(i, **j))
结果我发现,当 agreement 取了第一个值的时候,agentman 可以遍历一遍,但是,当 agreement 取第二个值一直到最后一个值的时候,无法进入 agentman 的循环了,j 一直等于 agentman 的最后一个值,感觉就像是 agentman 为空一样,最后的结果就是有且只有第一次的循环得到的一个合并之后的字典。
我本以为是因为生成器只能迭代一次。可当我又写了个小例子的时候,发现可以正常输出我想要的结果。
a = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}]
b = [{'a': 1, 'd': 14, 'e': 45}, {'a': 4, 'd': 24, 'e': 5}, {'a': 7, 'd': 34, 'e': 55}]
def ag():
for i in a:
yield i
def bg():
for j in b:
yield j
for i in ag():
for j in bg():
if i['a'] == j['a']:
print(dict(i, **j))
结果:
{'a': 1, 'b': 2, 'c': 3, 'd': 14, 'e': 45}
{'a': 4, 'b': 5, 'c': 6, 'd': 24, 'e': 5}
{'a': 7, 'b': 8, 'c': 9, 'd': 34, 'e': 55}
所以我选择就不明白到底是什么问题??
我的描述可以看的明白吧?
1
xuegj1010 OP 好像没法编辑代码的格式啊
|
2
ipwx 2018-05-18 10:04:52 +08:00 1
你的 agentman 怕不是一个迭代器。迭代器遍历完了就消耗完了,不会自动重启的。
你下面的小例子,bg() 每次都产生了一个新的迭代器。所以可以重复遍历。 |
3
guyskk0x0 2018-05-18 10:24:49 +08:00 via Android
理解 生成器函数,生成器,迭代器,列表 的区别和关联
|
5
yonoho 2018-05-18 10:27:34 +08:00
楼上解释了部分问题。对于两个 for 太丑的问题:当你使用两个序列类型配对的时候,因为你只能进行顺序查找,所以复杂度会是 O(n2)。那么你可以把一个较大的对象换成字典来实现 O(n) 配对。字典可以 ( key,value ) 元组为键,元素为值。
|
7
whoami9894 2018-05-18 11:23:26 +08:00 via Android
迭代器每一次执行__next()__方法后会记录当前变量值,所以一次循环结束会指向最后一个元素
可以在一次循环结束调用生成器的 send 函数,手动指向第一个元素 |
8
princelai 2018-05-18 12:10:40 +08:00
j = bg()
id(bg()) Out[125]: 139947918612704 id(bg()) Out[126]: 139947918289296 id(j) Out[127]: 139947918612176 id(j) Out[128]: 139947918612176 |
9
xuegj1010 OP @ipwx
```python class AgentmanReader(ReadExcel): def __init__(self, path): super(AgentmanReader, self).__init__(path) assert self.ncols == 27, 'columns must be 27' def parse_data(self): for i in range(1, self.nrows): agentman_dict = dict( # 公司名称(代理人名称)* agent_name=self.sheet.cell_value(i, 0), # 归属机构代码 org_code=str(self.sheet.cell_value(i, 1)), # 地址* address=self.sheet.cell_value(i, 2), # 邮编* postcode=self.sheet.cell_value(i, 3), # 业务渠道* trade_channel=str(TRADE_CHANNEL[self.sheet.cell_value(i, 4)]), # 代理人类型* agentman_type=str(AGENT_TYPE[self.sheet.cell_value(i, 5)]), # 许可证号* license_num=self.sheet.cell_value(i, 6), # 组织机构代码* social_code=self.sheet.cell_value(i, 7), # 负责人* principal=self.sheet.cell_value(i, 8), # 电话* phone=self.sheet.cell_value(i, 9), # 手机 mobile=self.sheet.cell_value(i, 10), # MAC 地址 mac_addr=self.sheet.cell_value(i, 11), # 资格证有效期 Validity=self.sheet.cell_value(i, 12), # 数字证书编码 digital_code=self.sheet.cell_value(i, 13), # 开户银行 opening_bank=self.sheet.cell_value(i, 14), # 户名 account_name=self.sheet.cell_value(i, 15), # 银行类别 bank_type=BANK_TYPE.get(self.sheet.cell_value(i, 16), '0'), # 省份 province=self.sheet.cell_value(i, 17), # 城市 city=self.sheet.cell_value(i, 18), # 银行帐号 bank_account=self.sheet.cell_value(i, 19), # 是否发送短信息 is_send=self.sheet.cell_value(i, 20), # 纳税人身份 taxpayer=self.sheet.cell_value(i, 21), # 纳税人识别号 taxpayer_num=self.sheet.cell_value(i, 22), # 纳税人地址 taxpayer_addr=self.sheet.cell_value(i, 23), # 纳税人电话 taxpayer_ph=self.sheet.cell_value(i, 24), # 纳税人开户行名称 taxpayer_bank=self.sheet.cell_value(i, 25), # 纳税人银行账号 taxpayer_account=self.sheet.cell_value(i, 26) ) yield agentman_dict agentman_data = AgentmanReader(AGENTMAN_PATH).parse_data() ``` excel 里面有几千条数据,读出来转换成一个生成器。 |
11
luhuisicnu 2018-05-18 14:27:22 +08:00
一个生成器只能遍历一次。
|
12
yonoho 2018-05-18 15:25:42 +08:00
|
13
princelai 2018-05-18 16:13:33 +08:00
读 excel 为什么不用 pandas
|
14
ipwx 2018-05-18 19:08:16 +08:00
@xuegj1010 agentman_data = AgentmanReader(AGENTMAN_PATH).parse_data()
这一条就是根本原因。agentman_data 现在只是一个迭代器,只能用一次。 |
19
yonoho 2018-05-22 10:10:58 +08:00 1
@xuegj1010
mans_agreements = {} # 假设 agreement 比较大 for a in agreement: mans_agreements.setdefault(a['agent_name'], []) mans_agreements[a['agent_name']].append(a) for man in agentman: his_agreements = mans_agreements.get(man['agent_name'], []) for a in his_agreements: print(dict(man, **a)) |