在字典列表中,如果 key/value 对的组合在另一个字典中相同,则标记一个字典
In a list of dicts, flag a dict if combination of key/value pairs is identical in another dict
我有一个字典列表,其中包含关键字 street
、number
和 some_flag
。
我的目标是在字典中搜索键 street
和 number
中的重复项。如果对于两个或多个字典,这两个 key/value 对相同,我想将值 1 分配给它们的 some_flag
键。
请参阅下面的可重现示例。
字典起始列表:
a = [
{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0},
]
预期输出:
a_checked = [
{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 1}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 1}, # duplicate street / number keys
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0},
]
我的最大努力:
到目前为止我得到的代码是从 Aarons 的回答中派生出来的 (here) and the community wiki's answer (here)
from collections import defaultdict, Counter
items = defaultdict(list) # create defaultdict
for row in a:
items[row['street']].append(row['number']) # make a list of 'number' values for each 'street' key
for key in items.keys():
if checkIfDuplicates(items[key]): #if there is more than one 'number' --> function definition see below
duplicate_dict = {}
duplicate_dict['numbers'] = [item for item, count in Counter(items[key]).items() if count > 1] # storing duplicate numbers in dict
duplicate_dict['street'] = key # storing street name in same dict
检查给定列表是否包含任何重复项的函数(来自here):
def checkIfDuplicates(listOfElems):
if len(listOfElems) == len(set(listOfElems)):
return False
else:
return True
当前输出:
print(duplicate_dict)
{'numbers': ['4'], 'street': 'ocean drive'}
使用我的方法,我现在必须将 duplicate_dict
与原始列表 a
匹配,这似乎效率不高。
有没有更直接的方法可以解决这个问题?
只需通过以下方式即可完成:
import pandas as pd
import numpy as np
# Your code
a = [
{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0},
]
# My code
data = pd.DataFrame(a)
data["some_flag"]= np.where(data.duplicated(keep=False), 1, data["some_flag"])
data
输出
street
number
some_flag
0
ocean drive
1
0
1
ocean drive
3
0
2
ocean drive
4
1
3
ocean drive
4
1
4
apple tree rd.
3
0
如果您对使用字典而不是数据框感兴趣,可以尝试使用 to_dict
函数将数据框更改为字典:
data.to_dict(orient="list")
这导致:
{'number': ['1', '3', '4', '4', '3'],
'some_flag': [0, 0, 1, 1, 0],
'street': ['ocean drive',
'ocean drive',
'ocean drive',
'ocean drive',
'apple tree rd.']}
说明
在数据帧上使用 duplicated
函数并将 False
分配给 keep
参数,您可以找到重复的行。然后使用 where
这是一个 numpy 函数,您可以根据逻辑语句为数组赋值。
您可以使用 dict.setdefault
首先存储列表的字典(其中键是“街道”和“数字”),然后遍历此字典的值以检查多个字典是否具有相同的值"street" 和 "number" 并修改其中多个的 "some_flag":
tmp = {}
for d in a:
tmp.setdefault((d['street'], d['number']), []).append(d)
out = []
for v in tmp.values():
if len(v) > 1:
for d in v:
d['some_flag'] = 1
out.extend(v)
输出:
[{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 1},
{'street': 'ocean drive', 'number': '4', 'some_flag': 1},
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0}]
你也可以在没有 pandas 的情况下使用更多代码来实现这一点,例如像这样:
import copy
a = [
{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0},
]
result = copy.deepcopy(a) #duplicate a to not override your input
last_entry = ""
for entry in result:
if last_entry == "": #skip first iteration to have two entries to compare
last_entry = entry
continue
if last_entry["street"] == entry["street"] and last_entry["number"] == entry["number"]:
last_entry["some_flag"] = 1
entry["some_flag"] = 1
last_entry = entry
print(result)
如果字典列表未排序,则我们必须检查每对可能的元素是否相等,这将花费 O(n^2)
时间。
但是,如果列表已排序,那么我们可以检查每个元素及其下一个元素,如果它们不相等,则没有必要使用后续元素检查该元素。另一方面,如果它们相等,我们继续检查下一个,依此类推。
def is_duplicate(d_1, d_2):
return d_1['street'] == d_2['street'] and d_1['number'] == d_2['number']
def set_duplicate(d_1, d_2):
d_1['some_flag'] = 1
d_2['some_flag'] = 1
a = sorted(a, key=lambda k: (k['street'].lower(), k['number']))
cur_index = 0
while cur_index < len(a):
next_index = cur_index + 1
while next_index < len(a) and is_duplicate(a[cur_index], a[next_index]):
set_duplicate(a[cur_index], a[next_index])
next_index += 1
cur_index += 1
print(a)
du = {}
for d in a:
new_key = d['street'] + "_" + d['number']
if new_key in du.keys():
du[new_key] = du[new_key] + 1
else:
du[new_key] = 1
print(du)
# {'ocean drive_1': 1, 'ocean drive_3': 1, 'ocean drive_4': 2, 'apple tree rd._3': 1}
for k, v in du.items():
if v > 1:
k1 = k.split("_")[0]
k2 = k.split("_")[1]
for d in a:
if d['street'] == k1 and d['number'] == k2:
d['some_flag'] = 1
print(a)
# [{'street': 'ocean drive', 'number': '1', 'some_flag': 0}, {'street': 'ocean drive', 'number': '3', 'some_flag': 0}, {'street': 'ocean drive', 'number': '4', 'some_flag': 1}, {'street': 'ocean drive', 'number': '4', 'some_flag': 1}, {'street': 'apple tree rd.', 'number': '3', 'some_flag': 0}]
我有一个字典列表,其中包含关键字 street
、number
和 some_flag
。
我的目标是在字典中搜索键 street
和 number
中的重复项。如果对于两个或多个字典,这两个 key/value 对相同,我想将值 1 分配给它们的 some_flag
键。
请参阅下面的可重现示例。
字典起始列表:
a = [
{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0},
]
预期输出:
a_checked = [
{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 1}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 1}, # duplicate street / number keys
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0},
]
我的最大努力:
到目前为止我得到的代码是从 Aarons 的回答中派生出来的 (here) and the community wiki's answer (here)
from collections import defaultdict, Counter
items = defaultdict(list) # create defaultdict
for row in a:
items[row['street']].append(row['number']) # make a list of 'number' values for each 'street' key
for key in items.keys():
if checkIfDuplicates(items[key]): #if there is more than one 'number' --> function definition see below
duplicate_dict = {}
duplicate_dict['numbers'] = [item for item, count in Counter(items[key]).items() if count > 1] # storing duplicate numbers in dict
duplicate_dict['street'] = key # storing street name in same dict
检查给定列表是否包含任何重复项的函数(来自here):
def checkIfDuplicates(listOfElems):
if len(listOfElems) == len(set(listOfElems)):
return False
else:
return True
当前输出:
print(duplicate_dict)
{'numbers': ['4'], 'street': 'ocean drive'}
使用我的方法,我现在必须将 duplicate_dict
与原始列表 a
匹配,这似乎效率不高。
有没有更直接的方法可以解决这个问题?
只需通过以下方式即可完成:
import pandas as pd
import numpy as np
# Your code
a = [
{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0},
]
# My code
data = pd.DataFrame(a)
data["some_flag"]= np.where(data.duplicated(keep=False), 1, data["some_flag"])
data
输出
street | number | some_flag | |
---|---|---|---|
0 | ocean drive | 1 | 0 |
1 | ocean drive | 3 | 0 |
2 | ocean drive | 4 | 1 |
3 | ocean drive | 4 | 1 |
4 | apple tree rd. | 3 | 0 |
如果您对使用字典而不是数据框感兴趣,可以尝试使用 to_dict
函数将数据框更改为字典:
data.to_dict(orient="list")
这导致:
{'number': ['1', '3', '4', '4', '3'],
'some_flag': [0, 0, 1, 1, 0],
'street': ['ocean drive',
'ocean drive',
'ocean drive',
'ocean drive',
'apple tree rd.']}
说明
在数据帧上使用 duplicated
函数并将 False
分配给 keep
参数,您可以找到重复的行。然后使用 where
这是一个 numpy 函数,您可以根据逻辑语句为数组赋值。
您可以使用 dict.setdefault
首先存储列表的字典(其中键是“街道”和“数字”),然后遍历此字典的值以检查多个字典是否具有相同的值"street" 和 "number" 并修改其中多个的 "some_flag":
tmp = {}
for d in a:
tmp.setdefault((d['street'], d['number']), []).append(d)
out = []
for v in tmp.values():
if len(v) > 1:
for d in v:
d['some_flag'] = 1
out.extend(v)
输出:
[{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 1},
{'street': 'ocean drive', 'number': '4', 'some_flag': 1},
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0}]
你也可以在没有 pandas 的情况下使用更多代码来实现这一点,例如像这样:
import copy
a = [
{'street': 'ocean drive', 'number': '1', 'some_flag': 0},
{'street': 'ocean drive', 'number': '3', 'some_flag': 0},
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'ocean drive', 'number': '4', 'some_flag': 0}, # duplicate street / number keys
{'street': 'apple tree rd.', 'number': '3', 'some_flag': 0},
]
result = copy.deepcopy(a) #duplicate a to not override your input
last_entry = ""
for entry in result:
if last_entry == "": #skip first iteration to have two entries to compare
last_entry = entry
continue
if last_entry["street"] == entry["street"] and last_entry["number"] == entry["number"]:
last_entry["some_flag"] = 1
entry["some_flag"] = 1
last_entry = entry
print(result)
如果字典列表未排序,则我们必须检查每对可能的元素是否相等,这将花费 O(n^2)
时间。
但是,如果列表已排序,那么我们可以检查每个元素及其下一个元素,如果它们不相等,则没有必要使用后续元素检查该元素。另一方面,如果它们相等,我们继续检查下一个,依此类推。
def is_duplicate(d_1, d_2):
return d_1['street'] == d_2['street'] and d_1['number'] == d_2['number']
def set_duplicate(d_1, d_2):
d_1['some_flag'] = 1
d_2['some_flag'] = 1
a = sorted(a, key=lambda k: (k['street'].lower(), k['number']))
cur_index = 0
while cur_index < len(a):
next_index = cur_index + 1
while next_index < len(a) and is_duplicate(a[cur_index], a[next_index]):
set_duplicate(a[cur_index], a[next_index])
next_index += 1
cur_index += 1
print(a)
du = {}
for d in a:
new_key = d['street'] + "_" + d['number']
if new_key in du.keys():
du[new_key] = du[new_key] + 1
else:
du[new_key] = 1
print(du)
# {'ocean drive_1': 1, 'ocean drive_3': 1, 'ocean drive_4': 2, 'apple tree rd._3': 1}
for k, v in du.items():
if v > 1:
k1 = k.split("_")[0]
k2 = k.split("_")[1]
for d in a:
if d['street'] == k1 and d['number'] == k2:
d['some_flag'] = 1
print(a)
# [{'street': 'ocean drive', 'number': '1', 'some_flag': 0}, {'street': 'ocean drive', 'number': '3', 'some_flag': 0}, {'street': 'ocean drive', 'number': '4', 'some_flag': 1}, {'street': 'ocean drive', 'number': '4', 'some_flag': 1}, {'street': 'apple tree rd.', 'number': '3', 'some_flag': 0}]