【问题标题】:Get count of tuples in list regardless of elements orders无论元素顺序如何,都获取列表中的元组数
【发布时间】:2018-04-09 02:08:24
【问题描述】:

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

my_list = [(1,12),(12,1),(12,1),(20,15),(7,8),(15,20)]

无论顺序如何,我都想计算数字组合。例如,如果要简单打印,我希望输出为:

1,12 = 3
20,15 = 2
7,8 = 1

基本上,我有一个连接列表,但方向无关紧要,所以 1 到 12 与 12 到 1 相同。

我已经为此工作了一段时间,但无法提出一个干净的解决方案。我想出的所有东西都必须检查两个方向,但是元组列表是随机的,所以涵盖所有可能性都是荒谬的。我可以很容易地用 set 或其他东西来计算唯一的元组,但同样,我考虑过的“双向”计数的每个解决方案都是草率的。

我觉得这应该不是很难,但是我在这方面工作了这么长时间,我已经彻底脑筋急转弯了。任何帮助将不胜感激!

【问题讨论】:

  • 不要列出列表,它会覆盖内置名称
  • 我没有,这只是一个例子。您对如何解决问题有任何想法吗?

标签: python list count tuples


【解决方案1】:

您可以使用collections.Counter,首先使用sorted 标准化您的元素。

from collections import Counter

lst = [(1,12),(12,1),(12,1),(20,15),(7,8),(15,20)]

count = Counter(tuple(sorted(t)) for t in lst)
# output: Counter({(1, 12): 3, (15, 20): 2, (7, 8): 1})

然后您可以像这样打印。

for value, amount in count.items():
    print(value, '=', amount)

# Prints: 
# (1, 12) = 3
# (15, 20) = 2
# (7, 8) = 1

【讨论】:

  • 这至少是一个n^2log(n) 解决方案,每次迭代都有sorted。我会考虑一种更有效的方法来组织每个元组。
  • Python 的Timsort 在短的、已经排序的序列上非常有效。调用 sorted 将使这一切都发生在 C 中,因此它可能会更有效。此外,它不是 n^2log(n),因为元组具有固定长度,它们的长度不是 n。因此它只是 O(n)
  • 承认输入中的元组很小,因此,sorted 在这种情况下并不是什么大问题,但是值得指出的是,对于大输入,效率会降低。但是我想一个人必须使用sorted。
  • 是的,如果你想规范化元组,你不能到处排序。
  • 啊,我没想到在计数之前对元组进行排序。现在看起来非常简单。很高兴当你因为一个问题工作太久而完全煎熬自己时出现堆栈溢出!
【解决方案2】:

首先你可以对你的列表进行排序

lst2 = [tuple(sorted(i)) for i in lst]

然后您可以使用set() 查找此列表中的唯一值并计算它们的出现次数。

count = {}
for i in set(lst2):
    num = len([1 for j in lst2 if j == i])
    count.update({i:num})
print(count)

{(1, 12): 3, (7, 8): 1, (15, 20): 2}

【讨论】:

    【解决方案3】:

    您可以尝试简单的方法,而无需像这样导入:

    my_list = [(1,12),(12,1),(12,1),(20,15),(7,8),(15,20)]
    
    count={}
    for i in my_list:
        if tuple(sorted(i)) not in count:
            count[tuple(sorted(i))]=1
        else:
            count[tuple(sorted(i))]+=1
    
    print(count)
    

    输出:

    {(15, 20): 2, (7, 8): 1, (1, 12): 3}
    

    【讨论】:

      【解决方案4】:

      您可以按大小交换所有位置,然后使用collections.counter:

      from collections import Counter
      l = [(1,12),(12,1),(12,1),(20,15),(7,8),(15,20)]
      new_l = Counter([[(b, a), (a, b)][a < b] for a, b in l])
      for a, b in new_l.items():
        print('{},{}:{}'.format(*(list(a)+[b])))
      

      输出:

      15,20:2
      7,8:1
      1,12:3
      

      【讨论】:

      • 完美!我以前从未使用过计数器。我知道有一种干净的方法可以做到这一点,但我错过了。如果我能提出这个答案,我会的,但我仍然不到 15 岁。谢谢!!
      • @neural_nomad 很高兴为您提供帮助!
      • 我没有投反对票,但我相信它要么是因为有些人发现使用 bool 作为索引不太可读,要么是因为您在每次迭代中生成一个列表和两个元组,而不是依赖于一些内置。无论如何,我确实认为这不是一个非常pythonic的答案。在我的书中不值得一票,但仍然。
      • 或者有人只是在投反对票。甚至我也无缘无故地得到了一个。
      • Downvote 通常应该只用于明显错误、非常不清楚或过时通知发布者的答案。但是会发生幽灵投票……没有批评就很烦人而且没用,但是我们能做些什么……
      猜你喜欢
      • 2017-09-27
      • 2016-06-28
      • 2013-11-30
      • 2019-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多