所以我有一个字典,其中标签是患者代码或姓名(字符串(,相关的数字是会诊时间(int(。例如,我有这样的:{'0001': 15, 'Charles': 20}
"0001"需要15分钟咨询,"Charles"需要20分钟咨询。
我事先不知道哪里有识别一个人的名字或号码(但它们都是字符串(,也就是说,我不知道Charles在字典中的位置,甚至不知道它是否存在
我想运行这本词典来检查有相同咨询时间的患者,如果他们有,我想运行某个不相关的功能。现在我有这个:
for pat_i in self.MD_dict:
for pat_j in self.MD_dict:
if(self.MD_dict[pat_i]==self.MD_dict[pat_j]):
aux=aux+1
funtion(pat_i, pat_j);
然而,我希望j从I+1开始。我该怎么做?
我试着使用测距功能:
for pat_i in range(len(self.MD_dict)):
for pat_j in range(i+1,len(self.MD_dict)):
if(self.MD_dict[pat_i]==self.MD_dict[pat_j]):
aux=aux+1
funtion(pat_i, pat_j);
但是因为pat_i可能是一个字符串,所以它不起作用。例如,在pat_i=1和pat_j=2的情况下,if工作所需的代码为"0001"和Charles。但是自从pat_i!='0001'和pat_j!='Charles的不起作用
在原始字典中,患者名称/id是关键字,时间是值。在新字典中,时间是关键字,paitent-name/id列表是值。
这是一个制作字典进行反向查找的想法,然后将具有相同时间的患者姓名/id组合到一个列表中。
def make_inverse_dict(x):
# Time is key. List of patients is value
time_dict = {}
for name, time in x.items():
if time in time_dict:
time_dict[time].append(name)
else:
time_dict[time] = [name]
return time_dict
def f(p1, p2):
print(f" {p1}, {p2}")
def make_patient_pair(patient_list):
# Triangular loop to make pairs of patients
# without duplication
n_patients = len(patient_list)
out = []
for i in range(n_patients):
for j in range(i):
pair = (patient_list[i], patient_list[j])
out.append(pair)
return out
def main():
patient_dict = {'0001': 15,
'0002': 10,
'Charles': 20,
'Ann': 20,
'0003': 15}
time_dict = make_inverse_dict(patient_dict)
for time, patient_list in time_dict.items():
n_patients = len(patient_list)
print("time: ", time)
if n_patients > 1:
for p1, p2 in make_patient_pair(patient_list):
f(p1, p2)
main()
结果:
time: 15
0003, 0001
time: 10
time: 20
Ann, Charles
代码的问题是您要多次迭代它。在第二次迭代中,检查MD_dict[pat_i]
是否等于MD_dict[pat_j]
。这意味着你将获得双倍的数据量,因为在某一点上,第二个循环将到达与第一个循环所在的点完全相同的点;查尔斯,";第二循环将首先在开始处开始,然后它将最终到达"0";查尔斯"显然;Charles";不会在第一个循环和第二个循环之间发生变化——这将导致一个实例,在该实例中;Charles";以及";Charles";进入你的功能,这不是你想要的。
假设MD_dict
是:
MD_dict = {'0001': 15, 'Charles': 20, '0002':15, 'Alex': 20, 'Jack':15}
我们能做的是使用enumerate
来确保这些重复不会发生:
pats = list(MD_dict.keys())
enum = list(enumerate(pats))
上面,enum
将患者的姓名和他们出现的索引配对:
[(0, '0001'), (1, 'Charles'), (2, '0002'), (3, 'Alex'), (4, 'Jack')]
然后,我们可以在enum
上迭代两次:
for x, pat_i in enum:
for y,pat_j in enum:
if x != y and MD_dict[pat_i] == MD_dict[pat_j]:
function(pat_i, pat_j) # apply function here
请注意x != y
在条件语句中的显示方式。这是为了避免将同一个人与自己配对。这确保了第二个循环不会考虑第一个循环所在的人。结果是:
function(0001, 0002) # consult times == 15
function(0001, Jack) # consult times == 15
function(Charles, Alex) # consult times == 20
function(0002, 0001) # consult times == 15
function(0002, Jack) # consult times == 15
function(Alex, Charles) # consult times == 20
function(Jack, 0001) # consult times == 15
function(Jack, 0002) # consult times == 15
然而,上面的函数有一个问题,我不完全清楚你在这个问题中要求什么。这个问题是该函数将被应用于";Charles";以及";Alex";然后";Alex";以及";Charles";这是因为我们把字典翻了两遍,所以它会找到";Alex";作为当第一循环命中"0"时的匹配;Charles";并且它将拾取";Charles";作为当第一循环命中"0"时的匹配;亚历克斯"如果这不是你想要的,我们可以在第二个循环上切片enum
:
pats = list(MD_dict.keys())
enum = list(enumerate(pats))
for x, pat_i in enum:
for y,pat_j in enum[x+1:]:
if MD_dict[pat_i] == MD_dict[pat_j]:
function(pat_i, pat_j) # apply function here
上面,for y,pat_j in enum[x+1:]
将只考虑第一个循环打开的人后面的人。然后我们不必检查x != y
。输出如下:
function(0001, 0002) # consult times == 15
function(0001, Jack) # consult times == 15
function(Charles, Alex) # consult times == 20
function(0002, Jack) # consult times == 15
sorted_items = sorted(self.MD_dict.items(), key=lambda x: x[1])
for i, (pat_i, pat_i_val) in enumerate(sorted_items):
for (pat_j, pat_j_val) in sorted_items[i+1:]
if pat_i_val == pat_j_val:
aux=aux+1
funtion(pat_i, pat_j)