【问题标题】:Compare multiple Lists only one time each in python在python中只比较多个列表一次
【发布时间】:2019-10-14 19:26:57
【问题描述】:

我遇到了一些代码问题。我希望我的代码比较多个列表中包含的 2 个列表,但每个列表只比较一次。

resultList = [
    ['Student1', ['Sport', 'History']],
    ['Student2', ['Math', 'Spanish']],
    ['Student3', ['French', 'History']],
    ['Student4', ['English', 'Sport']],
]

for list1 in resultList:
    for list2 in resultList:
        i = 0
        for subject in list1[1]:
            if subject in list2[1]:
                if list2[1].index(subject) >= list1[1].index(subject):
                    i+=1
                else:
                    i+=2
        print(list1[0] + ' - ' + list2[0] + ' : ' + str(i))

这打印:

Student1 - Student1 : 2
Student1 - Student2 : 0
Student1 - Student3 : 1
Student1 - Student4 : 1
Student2 - Student1 : 0
Student2 - Student2 : 2
Student2 - Student3 : 0
Student2 - Student4 : 0
Student3 - Student1 : 1
Student3 - Student2 : 0
Student3 - Student3 : 2
Student3 - Student4 : 0
Student4 - Student1 : 2
Student4 - Student2 : 0
Student4 - Student3 : 0
Student4 - Student4 : 2

我想要这个结果:

Student1 - Student1 : 2
Student1 - Student2 : 0
Student1 - Student3 : 1
Student1 - Student4 : 1
Student2 - Student2 : 2
Student2 - Student3 : 0
Student2 - Student4 : 0
Student3 - Student3 : 2
Student3 - Student4 : 0
Student4 - Student4 : 2

感谢您的帮助!

【问题讨论】:

    标签: python list loops


    【解决方案1】:

    你应该做得更清楚,

    只有 2 个循环,只有 3 行:

    for i in resultList:
        for j in resultList[resultList.index(i):]:
                print(str(i[0]) + '-' + str(j[0]) + ' : ' + str((np.isin(i[1], j[1]) == True).sum()))
    

    结果:

    Student1-Student1 : 2
    Student1-Student2 : 0
    Student1-Student3 : 1
    Student1-Student4 : 1
    Student2-Student2 : 2
    Student2-Student3 : 0
    Student2-Student4 : 0
    Student3-Student3 : 2
    Student3-Student4 : 0
    Student4-Student4 : 2
    

    欢迎您:)

    【讨论】:

    • 但是,numpy 在目标系统上可能不可用。它可能可以用列表理解中的简单 in 构造替换,例如 [x in j[1] for x in i[1]]
    • 是的,你完全正确,如果 numpy 不可用,使用 in 很棒。
    【解决方案2】:

    与原来相比,有两行修改和两行新的版本:

    resultList = [
    ['Student1', ['Sport', 'History']],
    ['Student2', ['Math', 'Spanish']],
    ['Student3', ['French', 'History']],
    ['Student4', ['English', 'Sport']],
    ]
    
    for index1 in range(0,len(resultList)):
        for index2 in range(index1, len(resultList)):
            i = 0
            list1 = resultList[index1]
            list2 = resultList[index2]
            for subject in list1[1]:
                if subject in list2[1]:
                    if list2[1].index(subject) >= list1[1].index(subject):
                        i+=1
                    else:
                        i+=2
            print(list1[0] + ' - ' + list2[0] + ' : ' + str(i))
    

    【讨论】:

    • 感谢您的帮助,我发现@Proyag 的解决方案非常简单。
    【解决方案3】:

    我认为,你应该做得更清楚:)。

    也许可以尝试这种方式,使用 OOP:

    import itertools.combinations
    
    class Student:
        def __init__(self, name, subjects):
            self.name = name
            self.subjects = subjects
    
        def compare_to(self, another_student):
            result = 0
            for subject_my in self.subjects:
                for subject_he in another_student.subjects:
                    if self.subjects.index(subject_my) >= \   
                            another_student.subjects.index(subject_he):
                        result+=1
                    else:
                        result+=2
           return result
    
    resultList = [
        Student('Student1', ['Sport', 'History']),
        Student('Student2', ['Math', 'Spanish']),
        Student('Student3', ['French', 'History']),
        Student('Student4', ['English', 'Sport'])
        ]
    
    for first, secound in itertools.combinations(resultList):
        print("{} - {} : {}".format(first.name, secound.name, first.compare_to(secound)))
    

    我认为,它应该看起来更干净,更易读:)。选择当然是你的。 清晰的代码,将简化您发现问题所在的机会。

    【讨论】:

    • 非常感谢您的回答!这是一个非常好的方法。
    • 我的错。我使用组合而不是另一个重复的迭代工具,限制为 2 个元素。无论如何... itertools.combinations_with_replacement(resultList, 2)如果你改变它,这会很好:)
    【解决方案4】:

    这个想法类似于@yatu的回答,但不是手动保持计数,您可以使用enumerate,并仅迭代list1中当前索引之后的list2部分。如果您想避免 1-1 2-2 对,只需使用 resultList[idx+1:] 而不是 resultList[idx:]

    resultList = [                                                                                                                 
        ['Student1', ['Sport', 'History']],                                                                                        
        ['Student2', ['Math', 'Spanish']],                                                                                         
        ['Student3', ['French', 'History']],                                                                                       
        ['Student4', ['English', 'Sport']],                                                                                        
    ]                                                                                                                              
    
    for idx, list1 in enumerate(resultList):                                                                                       
        for list2 in resultList[idx:]:                                                                                             
            i = 0                                                                                                                  
            for subject in list1[1]:                                                                                               
                if subject in list2[1]:                                                                                            
                    if list2[1].index(subject) >= list1[1].index(subject):                                                         
                        i+=1                                                                                                       
                    else:                                                                                                          
                        i+=2                                                                                                       
            print(list1[0] + ' - ' + list2[0] + ' : ' + str(i))
    

    【讨论】:

      【解决方案5】:

      您可以使用set.intersection来比较列表:

      resultList = [
          ['Student1', ['Sport', 'History']],
          ['Student2', ['Math', 'Spanish']],
          ['Student3', ['French', 'History']],
          ['Student4', ['English', 'Sport']],
      ]
      
      s = set()
      for list1 in resultList:
          for list2 in resultList:
              i = tuple(sorted([list1[0], list2[0]]))
              if i in s:
                  continue
              s.add(i)
              print(list1[0], list2[0], len(set(list1[1]).intersection(list2[1])))
      

      打印:

      Student1 Student1 2
      Student1 Student2 0
      Student1 Student3 1
      Student1 Student4 1
      Student2 Student2 2
      Student2 Student3 0
      Student2 Student4 0
      Student3 Student3 2
      Student3 Student4 0
      Student4 Student4 2
      

      【讨论】:

        【解决方案6】:

        我会使用itertools.combinations_with_replacementitertools.combinations

        In [1]: resultList = [
           ...:     ['Student1', ['Sport', 'History']],
           ...:     ['Student2', ['Math', 'Spanish']],
           ...:     ['Student3', ['French', 'History']],
           ...:     ['Student4', ['English', 'Sport']],
           ...: ]
           ...:
        
        In [2]: import itertools
        In [3]: new_result = itertools.combinations_with_replacement(resultList, 2)
        In [4]: for lists_tuple in new_result:
            ...:     list1, list2 = lists_tuple
            ...:     i = 0
            ...:     for subject in list1[1]:
            ...:         if subject in list2[1]:
            ...:             if list2[1].index(subject) >= list1[1].index(subject):
            ...:                 i+=1
            ...:             else:
            ...:                 i+=2
            ...:     print(list1[0] + ' - ' + list2[0] + ' : ' + str(i))
            ...:
            ...:
        Student1 - Student1 : 2
        Student1 - Student2 : 0
        Student1 - Student3 : 1
        Student1 - Student4 : 1
        Student2 - Student2 : 2
        Student2 - Student3 : 0
        Student2 - Student4 : 0
        Student3 - Student3 : 2
        Student3 - Student4 : 0
        Student4 - Student4 : 2
        

        combinations

        如果您决定不想将每个列表与其自身进行比较 (Student1 - Student1),请将 combinations_with_replacement 更改为 combinations,您将获得列表不同元素之间的比较:

        Student1 - Student2 : 0
        Student1 - Student3 : 1
        Student1 - Student4 : 1
        Student2 - Student3 : 0
        Student2 - Student4 : 0
        Student3 - Student4 : 0
        

        【讨论】:

        • 谢谢,作为初学者,这似乎有点难,所以我选择了@Proyag 的解决方案。
        • 没问题。 itertools 是 Python 中一个非常有用的模块,你可以随时尝试它的一些方法。
        猜你喜欢
        • 1970-01-01
        • 2019-04-04
        • 2022-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多