【问题标题】:Removing a tuple from list of tuples从元组列表中删除一个元组
【发布时间】:2017-07-10 00:32:14
【问题描述】:

我有一个看起来像这样的元组列表;

ListTuples = [('192.168.1.100', '192.168.1.101'), ('192.168.1.100', '192.168.1.102'), ('192.168.1.100', '192.168.1.103'), ('192.168.1.103', '192.168.1.100')]

当元组的第一个元素与另一个元组的第二个元素匹配时,我想删除元组,同时元组的第二个元素与另一个元组的第一个元素匹配。 OutputList 将如下所示;

OutputList = [('192.168.1.100', '192.168.1.101'), ('192.168.1.100', '192.168.1.102')]

除了遍历所有元组以比较并保存到新的元组列表之外,还有更简单的方法吗?

谢谢。

【问题讨论】:

    标签: python list tuples


    【解决方案1】:

    制作两组:第一组包含原始元组,第二组包含交换了元素的元组。然后取两组的交集。这些是要删除的元组。用所有元组创建一个新列表,但这些元组除外:

    >>> ListTuples = [('192.168.1.100', '192.168.1.101'), ('192.168.1.100', '192.168.1.102'), ('192.168.1.100', '192.168.1.103'), ('192.168.1.103', '192.168.1.100')]
    >>> set1 = set(ListTuples)
    >>> set2 = set((e2, e1) for e1, e2 in ListTuples)
    >>> to_remove = set1 & set2
    >>> to_remove
    set([('192.168.1.103', '192.168.1.100'), ('192.168.1.100', '192.168.1.103')])
    >>> NewList = [t for t in ListTuples if t not in to_remove]
    >>> NewList
    [('192.168.1.100', '192.168.1.101'), ('192.168.1.100', '192.168.1.102')]
    

    这将是 O(n),而搜索列表将是 O(n**2)。

    【讨论】:

      【解决方案2】:

      好吧,如果你想将它们相互比较,你必须遍历你的元组,但至少你可以使用一个带有反转元素的临时集合来更快地查找:

      ListTuples = [('192.168.1.100', '192.168.1.101'), ('192.168.1.100', '192.168.1.102'),
                    ('192.168.1.100', '192.168.1.103'), ('192.168.1.103', '192.168.1.100')]
      
      seen = set()
      for element in ListTuples:
          if element in seen:
              seen.discard(element)
          else:
              seen.add(tuple(reversed(element)))
      OutputList = [tuple(reversed(element)) for element in seen]
      
      print(OutputList)  # [('192.168.1.100', '192.168.1.101'), ('192.168.1.100', '192.168.1.102')]
      

      它不会保持顺序,但是。

      【讨论】:

        【解决方案3】:

        使用collections.Counter统计每个排序后的元组出现的次数,然后过滤掉那些计数大于1的元组:

        from collections import Counter
        
        ListTuples = [('192.168.1.100', '192.168.1.101'), ('192.168.1.100', '192.168.1.102'), ('192.168.1.100', '192.168.1.103'), ('192.168.1.103', '192.168.1.100')]
        
        counts = Counter(tuple(sorted(t)) for t in ListTuples)
        OutputList = [k for k in counts if counts[k] == 1]
        
        >>> OutputList
        [('192.168.1.100', '192.168.1.101'), ('192.168.1.100', '192.168.1.102')]
        

        请注意,这不会保留原始列表中项目的顺序;我不知道在这种情况下这对你是否重要。

        此外,它对每个元组进行排序有点低效,但必须考虑项目顺序,如果在一般情况下每个元组可以有超过 2 个元素,则对元组进行排序将是要走的路。

        你可以像这样使它成为一个单行:

        OutputList = [k for k, count in Counter(tuple(sorted(t)) for t in ListTuples).items() if count == 1]
        

        【讨论】:

          猜你喜欢
          • 2017-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-09
          • 1970-01-01
          相关资源
          最近更新 更多