请教思路算法,或者用什么轮子会更高效?
毕竟整个 List 还是挺大的,7 到 8 万个元素,
今天试着用 for,for,for 来整,不太成功,而且解决思路线径还把自己绕晕了
后来想着是放入 Mysql 搞的,但考虑到使用环境,不太现实
今天试着用 pandas 来弄了一下,结果还把自己弄晕在 index 和 row 的事情上了
AList = [{'型号': 12, '重量': 16, '产地': 19,'审核人':33},
{'型号': 22, '重量': 92, '产地': 87,'审核人':34},
{'型号': 15, '重量': 27, '产地': 86,'审核人':35},
{'型号': 71, '重量': 55, '产地': 21,'审核人':36}]
BList = [{'产地': 87, '型号': 22, '重量': 92,'审核人':34},
{'产地': 86, '型号': 15, '重量': 27,'审核人':35},
{'产地': 44, '型号': 65, '重量': 91,'审核人':33}]
A,B 两个列表每个元素都是一个字典
A,B 两个 List 选择性进行合并,得出 CList
例子是只有四个 k/v 对, 但实际字典很多 k/v 对,而且每个字典里面的键值对的数量,也不尽相同
合并有以下去重条件:
只以型号, 重量, 审核人三个 value 作为去重判断,
A,B 两个列表,如果有这三个 value 重复, 只保留 AList 内容(整个字典)加入到 CList
BList 里面字典里三个 value 不重复的,整个字典作为元素加入到 CList
1
1373569162 2020-02-26 20:20:36 +08:00
构造一个 dict,型号, 重量, 审核人拼接起来作为 key,遍历两个 list,key 不在 dict 里就加进去,最后输出 dict.values()
|
2
epicnoob 2020-02-26 22:24:09 +08:00
f = lambda _: (_['产地'], _['型号'], _['重量'])
t = sorted(AList+BList, key=f) CList = reduce(lambda l, v: l + [v] if f(l[-1]) != f(v) else l, t, [t[0]]) |
3
epicnoob 2020-02-26 22:25:03 +08:00
排序是稳定的,相同值肯定是 Alist 的在前面
|
4
ferstar 2020-02-26 22:50:52 +08:00
python >= 3.6
```python3 a_list = [ {"型号": 12, "重量": 16, "产地": 19, "审核人": 33}, {"型号": 22, "重量": 92, "产地": 87, "审核人": 34}, {"型号": 15, "重量": 27, "产地": 86, "审核人": 35}, {"型号": 71, "重量": 55, "产地": 21, "审核人": 36}, ] b_list = [ {"产地": 87, "型号": 22, "重量": 92, "审核人": 34}, {"产地": 86, "型号": 15, "重量": 27, "审核人": 35}, {"产地": 44, "型号": 65, "重量": 91, "审核人": 33}, ] def generate_key(item): return "_".join(v for k, v in item.items() if k != "型号") hash_map = {} for item in a_list: hash_map.setdefault(generate_key(item), item) for item in b_list: hash_map.setdefault(generate_key(item), item) c_list = list(hash_map.values()) ``` |
5
MoYi123 2020-02-26 22:57:20 +08:00
tmp = set()
rt = [] for i in AList + BList: t = (i['型号'], i['重量'], i['审核人']) if t not in tmp: tmp.add(t) rt.append(i) |
6
ferstar 2020-02-26 23:05:45 +08:00
|
7
bugmakerxs 2020-02-26 23:12:58 +08:00
就用 mysql 啊
|
8
bugmakerxs 2020-02-26 23:16:11 +08:00
型号+重量+产地 md5 做 key,该行数据为 value 放入一个字典,Blist 先放进去,alist 后放进去。或者直接做张标,key 做唯一索引
|
9
BlackBerry999 2020-02-27 08:34:11 +08:00
构建一个 3 层的多叉树,一层型号,二层重量,三层审核人。然后遍历 AB 两个 list 构建 3 层多叉树,并且来自于 AList 的值可以覆盖重写叶子节点。
|
10
wuwukai007 2020-02-27 10:54:29 +08:00
逻辑梳理一下,
第一、A 与 B 找固定那三个列的重复,重复的值只保留 原 A 的,保存到 c 第二,B 根据三列去重后,并且不在刚刚第一步 的结果中 保存到 c 第三、A 根据三列去重,保存到 c |
11
wuwukai007 2020-02-27 11:19:45 +08:00
regex = ['型号','审核人','重量']
d1 = pd.DataFrame(a_list).drop_duplicates(regex) d2 = pd.DataFrame(b_list).drop_duplicates(regex) buf = d1.merge(d2,on=regex,how='inner') new_col = [col for col in buf.columns.tolist() if str(col).endswith('_x')] + regex buf_c = buf[new_col] buf_c.columns = [str(col).replace('_x','') for col in buf_c.columns.tolist()] c1 = d1.append(buf_c).drop_duplicates(regex).to_dict(orient="records") c2 = d2.to_dict('records') c_list = c1 + c2 |
12
wuwukai007 2020-02-27 11:43:21 +08:00
还有我试了下 几万条数据 就算用纯 for 循环写,也不慢的吧。
|
13
MisterLee 2020-02-27 17:29:49 +08:00
——Python&Pandas
a_df= pd.DataFrame(a_list) b_df= pd.DataFrame(b_list) a_b_df = pd.concat([a_df, b_df], axis=0).drop_duplicates(['型号', '重量', '审核人'], keep='first') c_list = [] for _, item in a_b_df.iterrows(): c_list.append(item.dropna().to_dict()) |
14
wdc63 2020-02-27 18:35:39 +08:00
@bugmakerxs 嗯,遍历列表 A,以型号, 重量, 审核人的值做 key,下标做 value,建立 hash 表,遍历列表 B,查找每一个元素是否在 hash 表中,有的话合并到 Alist,没有的话添加到 Alist 末尾,每个字典都很简单,合并过程复杂度可以认为是 O(1),整个算法复杂度为 O(M+N),应该是效率最高的算法了。
|