1

我有这个学校的代码,其目标是从代表人的价值观列表中列出所有相互关系(两个人互相请求的时间)。

我正在使用的列表是:

1,9,11,15,20,3 
2,29,22,5,21,8  
3,2,30,16,27,2
4,21,17,25,6,4
5,15,2,18,6,24
6,1,18,19,29,4
7,30,17,30,18,15
8,10,2,6,26,12
9,21,30,12,29,14

我必须找到相互的代码是:

i=0
j=0
k=0
l=0
mutuals = []

for i in range(0,8):
    for j in range(i+1, 8):
        for k in range(1,5):
            if content2[j][k] == content2[i][0]:
                for l in range(1,5):
                    if content2[j][0] == content2[i][l]:
                       mutuals.append(content2[i][0])
                       mutuals.append(content2[j][0])
                       #print(mutuals)
                       print(i,j,k,l)
                       l=0
                    print(i,j,k,l)
            print(i,j,k,l)
     print(i,j,k,l)
print(i,j,k,l)
print(mutuals)

我列出'print(i,j,k,l)'的原因是我可以尝试看看代码中出了什么问题。

输出是:['2','5']

即使也应该有相互的 ['2','8'] 和 ['4','6'] ,但我无法弄清楚代码有什么问题。

如何修复代码,以便其他互斥量也打印为输出?

4

3 回答 3

1

解决方案

你的问题是你的使用range(start,stop)- 'stop' 值不包括在内,所以如果你想测试到nth 值,你需要把n+1它作为第二个参数。

IE

#...
for i in range(0,9):
    for j in range(i+1, 9):
        for k in range(1,6):
            if content2[j][k] == content2[i][0]:
                for l in range(1,6):
#...

如您所见, of 的“相互”2是其列表中的最后一个参数,与:[2,29,22,5,21,8]的相互也是如此。6[6,1,18,19,29,4]

由于您的 range 循环 forl并且k仅 check range(1,5),因此它们不会检查最终条目,并且不会将它们识别为相互的。


代码审查

注意:您不需要初始化值i,j,k,l,因为它们在for循环的第一次迭代中被重置为 的第一个值range

您也不需要重置l0,因为它是未使用的(在您的打印语句中除外),直到它在其for循环中被重置。


注意:实现这一点的更简单的方法是:

for entry in nums:
    for test in nums[entry[0]:]:
        if entry[0] in test[1:] and test[0] in entry[1:]:
            print test[0], entry[0]
于 2018-05-31T15:48:19.870 回答
0

而不是大规模嵌套循环方法和跟踪一堆列表索引,我会建立一个对的列表,这样你就可以轻松测试它们之前是否出现过(除非你会遇到内存问题,否则没有复制/修改您的数据的危害)。

requests = [
[1,9,11,15,20,3],
[2,29,22,5,21,8], 
[3,2,30,16,27,2],
[4,21,17,25,6,4],
[5,15,2,18,6,24],
[6,1,18,19,29,4],
[7,30,17,30,18,15],
[8,10,2,6,26,12],
[9,21,30,12,29,14]
]
all_pairs = []

#create one big list of pairs
for person in requests:
    pairs = []
    user_id = person[0]

    for other_person in person[1:]:
        pairs.append({user_id, other_person}) # add to the list of pairs (we use set so the order of the pair doesn't matter)
    all_pairs += pairs #add the pairs from one person to the global list

matches = []

#iterate over that list and check if we've seen that pair before
for index, pair in enumerate(all_pairs):
    if pair in pairs[:index]: #if we've seen it before
        matches.append(pair) #add it to our matches (if a pair is encountered a third time, it'll be added to matches twice)       

这可以写得更紧凑、更有效,但我的目标是让流程更容易理解。

于 2018-05-31T15:42:51.450 回答
0

而不是调试您的代码,这是一个替代解决方案,它可以为您提供一些不同的方式来思考您的问题

# Load the data as given
c2 = [[1,9,11,15,20,3],
     [2,29,22,5,21,8 ], 
     [3,2,30,16,27,2],
     [4,21,17,25,6,4],
     [5,15,2,18,6,24],
     [6,1,18,19,29,4],
     [7,30,17,30,18,15],
     [8,10,2,6,26,12],
     [9,21,30,12,29,14]]

# Convert it to a dictionary where the key is the person, and
# the value is a set of people they requested
c3 = { l[0]: set(l[1:]) for l in c2}

# Now crudely iterate through each person checking if
# they appear in the requests for each person they
# requested.
m = set()
for me,l in c3.items():
    for them in l:
        if me != them and me in c3.get(them,set()):
            # add the pair as a sorted tuple and let the set
            # deduplicate
            m.add(tuple(sorted([me,them])))
print(m)

这输出

{(2, 5), (2, 8), (4, 6)}

这似乎效率低下,但大多数搜索都是使用 set access 完成的,这是恒定的时间。这些对作为元组而不是列表添加,因为它们是不可变的,因此是可散列的(您不能将列表放入集合中)。

这只是为了让您考虑使用不同的数据结构以及它们如何显着改变您的算法选择。

一旦你明白了这一点,那么整个循环就可以被重写为一个集合理解

m = { tuple(sorted([me,them])) 
      for me in c3.keys() 
      for them in c3[me] 
      if me != them and me in c3.get(them,set())
     }
于 2018-05-31T15:43:59.977 回答