【问题标题】:How to keep ordered list using 'set'?如何使用'set'保持有序列表?
【发布时间】:2018-08-13 23:01:08
【问题描述】:

我希望能够在比较时保持列表的顺序。请注意,当我将 list1 与 list2 进行比较时,它会返回 8,然后返回 7(反向)。我如何让它维持秩序?

>>> list1 = ['1','2','3','4','7','8'] 
>>> list2 = ['1','2','3','4','5','6']
>>> list(set(list2) - set(list1))    
['5', '6']
>>> list(set(list1) - set(list2))    
['8', '7']

【问题讨论】:

  • 您想要列表中给出的顺序还是想要对集合差异的结果进行排序?
  • 对,所以我希望从给定的原始列表中维护订单。换句话说,预期的输出应该是 ['7', '8'] ......但是,我也需要应用于字符串(保持列表的顺序)而不是数字“排序”。

标签: python list set


【解决方案1】:

OrderedDict 可以很好地替代保序集,因为键视图类似于集合:

>>> from collections import OrderedDict
>>> list1 = ['1','2','3','4','7','8'] 
>>> list2 = ['1','2','3','4','5','6']
>>> OrderedDict.fromkeys(list1).keys() - OrderedDict.fromkeys(list2).keys()
{'7', '8'}
>>> OrderedDict.fromkeys(list2).keys() - OrderedDict.fromkeys(list1).keys()
{'5', '6'}

严格来说,那可能还在使用 CPython 的实现细节。但是列表理解不是,它们仍然是 O(n):

>>> od1 = OrderedDict.fromkeys(list1)
>>> od2 = OrderedDict.fromkeys(list2)
>>> [k for k in od1 if k not in od2]
['7', '8']
>>> [k for k in od2 if k not in od1]
['5', '6']

【讨论】:

  • 在 Python 3.6+ 中,dict 插入是有序的,所以你可以使用dict.fromkeys()
  • @pylang 不完全是。 Python 3.7+ 或 CPython 3.6+。
  • 设置差异解决方案不起作用。结果的顺序是随机的。
  • @Aran-Fey 我找不到odict_keys 视图随机返回的 Python 版本(尽管它可能未指定)。无论如何,我不会把它作为一个完整的解决方案来展示,只是一个视图是 set-like 的演示。
  • @Aran-Fey。是的,但我认为细节有点迂腐。我怀疑 python 标签本质上是指 CPython 实现。无论如何,谢谢。
【解决方案2】:

您可以使用列表推导:

list1 = ['1','2','3','4','7','8'] 
list2 = ['1','2','3','4','5','6']

set1 = set(list1)  # convert to set for faster membership testing
result = [x for x in list2 if x not in set1]
# result: ['5', '6']

但是,这将包含重复的元素:

>>> list1 = [1]
>>> list2 = [1, 2, 2]
>>> set1 = set(list1)
>>> [x for x in list2 if x not in set1]
[2, 2]

如果不需要重复,只需将列表推导转换为循环并跟踪您已经遇到的所有元素:

list1 = [1] 
list2 = [1, 2, 2]

set1 = set(list1)
result = []

for x in list2:
    if x in set1:
        continue

    result.append(x)
    set1.add(x)

# result: [2]

【讨论】:

  • 如果原始列表包含重复项怎么办?
  • @Akavall 您必须询问 OP 在这种情况下会发生什么。
  • 在我看来,OP 想要在保留订单的情况下设置差异。
  • @Akavall 然后你用collections.Counter而不是集合做类似的事情。
  • 看起来不错,我不是投反对票的人,所以我无法撤消!
【解决方案3】:

虽然这不使用 - 运算符来表示集合,但它确实保留了原始列表的顺序。

list1 = ['1','2','3','4','7','8'] 
list2 = ['1','2','3','4','5','6']
set_list2 = set(list2)
result = []
for item in list1:
    if not item in set_list2:
        result.append(item)
        set_list2.add(item) # to avoid duplicates in result
print(result)
# ['7', '8']

【讨论】:

  • 我认为更新 set_list2 以跟踪添加到 result 的项目,因此不再添加相同的元素一次更符合 OP 问题的精神。
【解决方案4】:

根据定义,“集合”是无序的。如果您想对元素进行排序,请尝试使用列表操作。你可以使用 numpy 中的setdiff1d,例如:

import numpy as np
list1 = ['1','2','3','4','7','8'] 
list2 = ['1','2','3','4','5','6']
new_list_one = np.setdiff1d(list2, list1)
new_list_two = np.setdiff1d(list1, list2)

print(new_list_one) ['5' '6']
print(new_list_two) ['7' '8']

【讨论】:

    【解决方案5】:

    您可以改用列表推导来找出差异。这是您的操作方法: [x for x in list1 if x not in list2] 将产生 ['7', '8']

    你可以使用[x for x in list2 if x not in list1] 得到['5', '6']

    如果原始列表包含重复项,您可以使用[x for x in list1 if x not in list2 and list1.count(x) == 1]

    【讨论】:

      【解决方案6】:

      可能是最幼稚的做法:

      def ordered_diff(a, b):
          seen = set(b)
          result = []
          for ele in a:
              if ele not in seen:
                  result.append(ele)
                  seen.add(ele)
      
          return result     
      
      
      list1 = ['1','2','3','4','7','8','7','8'] 
      list2 = ['1','2','3','4','5','6','5','6']
      
      print ordered_diff(list1, list2)
      print ordered_diff(list2, list1)
      

      结果:

      ['7', '8']
      ['5', '6']
      

      【讨论】:

        【解决方案7】:

        在这种情况下,只需使用列表推导:

        [x for x, y in zip(b, a) if x != y]
        # ['5', '6']
        
        [x for x, y in zip(a, b) if x != y]
        # ['7', '8']
        

        一般来说,考虑itertools.zip_longest(与zip 相比),尤其是不同长度的列表。

        【讨论】:

          猜你喜欢
          • 2020-01-18
          • 1970-01-01
          • 2022-12-24
          • 1970-01-01
          • 2011-09-21
          • 2012-09-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多