【问题标题】:Obtaining a list of ordered integers from a list of "pairs" in Python从 Python 中的“对”列表中获取有序整数列表
【发布时间】:2020-02-25 12:31:31
【问题描述】:

您好,我目前正在处理大量数据,其中包含偶数个整数,所有整数都有一个匹配值。我正在尝试在 Python 中创建一个由“一对”组成的列表。我可以拥有多对相同的值,因此仅使用 set 函数不起作用。例如,如果我有一个列表:

List = [10, 10, 11, 20, 15, 20, 15, 11, 10, 10]

在此示例中,索引 01 将是一对,然后是 2735468 和 @ 987654332@.

我想从该列表中提取构成每一对的值,并使用所述值创建一个新列表以生成如下内容:

newList = [10, 11, 20, 15, 10]

使用 set 函数使得整个数据集中只有一个元素被放入列表中,我需要来自 List 的总数据的一半。对于我有不止一对相同值的情况,它看起来像这样:

List = [10, 10, 11, 10, 11, 10]

需要生成如下列表:

newList = [10, 11, 10]

任何见解都会很棒,因为我是 Python 新手,而且有很多我可能不知道的功能。

谢谢

【问题讨论】:

  • 我不确定我是否理解这里的“配对”。您可以通过去重整个列表(例如set(List))简单地实现您想要的输出,而无需过多关心“对”......
  • [1, 1, 1] 的输出应该是什么?您的输入是否仅包含对?这个问题对我来说似乎没有很好的定义......
  • @deceze 对整个列表进行重复数据删除的问题是,如果我有两对,例如[10, 10, 10, 10],我需要一个包含两个元素的新列表,每对一个元素。我还需要保持未排序的顺序列表的格式。
  • @hiroprotagonist 对我来说永远不会有这种情况,List 的每个值的数量总是相等的。
  • 这里的“对”是怎么定义的,还不是很清楚。

标签: python algorithm list


【解决方案1】:

试试吧:

new_list = set(list)

这应该会返回您想要的输出。

【讨论】:

  • 这种方法似乎没有产生预期的结果,因为每个方法不止一对。例如,我可能会遇到四个相同整数或两对整数的情况。在这种情况下,我希望 newList 包含两个元素,每对一个。
【解决方案2】:

如果我理解正确,您不希望有任何重复的值,希望保留一个具有来自特定列表的唯一值的列表。

如果我是对的,一个简单的方法是:

List = [10, 10, 11, 11, 15, 20, 15, 20]
newList = []
for x in List:
    if x not in newList:
        newList.append(x)

print(newList)

类似python的方法是:

newList = set(List)

【讨论】:

    【解决方案3】:

    这是@Alain T 的答案之一的细微变化:

     [i for s in [set()] for i in List if (s.remove(i) if i in s else (not s.add(i)))] 
    

    注意:以下是我在添加订购要求之前的回答

    sorted(List)[::2]
    

    这会对输入List 进行排序,然后从每两个连续的值中只取一个值。

    【讨论】:

    • 这不会保留原始顺序,如 OP 的第二个示例所示。
    • 我回答时这个约束不存在...我更新了我的答案
    【解决方案4】:

    作为一般方法,可以这样做:

    l = [10, 10, 11, 20, 15, 20, 15, 11, 10, 10]
    i = 0
    while i < len(l):
        del l[l.index(l[i], i + 1)]
        i += 1
    

    它逐个遍历列表,找到当前值下一个出现的索引,并将其删除,从而缩短列表。这可能可以用各种方式来修饰,但它是一个简单的算法。如果一个数字没有有匹配的对,这将引发ValueError

    【讨论】:

    • 问题是,这不会删除第二对相同的对吗?
    • 它只删除每对的第二项。 list.index 只找到第一个后续出现,并且每对只执行一次。
    【解决方案5】:

    以下代码创建了一个新列表,其中包含输入列表中出现的项目数量的一半。顺序是输入列表中第一次出现的顺序。

    >>> from collections import Counter
    >>> d = [10, 10, 11, 20, 15, 20, 15, 11, 10, 10]
    >>> c = Counter(d)
    >>> c
    Counter({10: 4, 11: 2, 20: 2, 15: 2})
    >>> answer  = sum([[key] * (val // 2) for key, val in c.items()], [])
    >>> answer
    [10, 10, 11, 20, 15]
    >>> 
    

    【讨论】:

      【解决方案6】:

      如果您需要保留每对第一次出现的顺序,您可以使用对值进行 XOR 操作的集合来在第一次和第二次出现之间交替。

      List = [10, 10, 11, 20, 15, 20, 15, 11, 10, 10]
      
      paired = [ i for pairs in [set()] for i in List if pairs.symmetric_difference_update({i}) or i in pairs]
      print(p)
      # [10, 11, 20, 15, 10]
      

      您也可以使用 itertools 中的累积函数来做到这一点:

      from itertools import accumulate
      paired = [a for a,b in zip(List,accumulate(({n} for n in List),set.__xor__)) if a in b]
      print(paired)
      # [10, 11, 20, 15, 10]
      

      或者使用位图而不是集合(如果您的值是相对较小的正整数(例如 0 到 64 之间):

      paired = [ n for n,m in zip(List,accumulate((1<<n for n in List),int.__xor__)) if (1<<n)&m ]
      print(paired)
      # [10, 11, 20, 15, 10]
      

      或者您可以使用集合中的计数器

      from collections import Counter
      paired = [ i for c in [Counter(List)] for i in List if c.update({i:-1}) or c[i]&1 ]
      print(paired)
      # [10, 11, 20, 15, 10]
      

      而且,如果您不太担心效率,可以使用 2 步跨步的双重排序:

      paired = [List[i] for i,_ in sorted(sorted(enumerate(List),key=lambda n:n[1])[::2])]
      print(paired)
      # [10, 11, 20, 15, 10]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-18
        • 1970-01-01
        • 2016-08-01
        • 2013-09-15
        • 1970-01-01
        • 2022-10-12
        • 1970-01-01
        • 2013-03-30
        相关资源
        最近更新 更多