【问题标题】:Find most common string in a 2D list在二维列表中查找最常见的字符串
【发布时间】:2019-04-25 17:43:06
【问题描述】:

我有一个二维列表:

arr = [['Mohit', 'shini','Manoj','Mot'],
      ['Mohit', 'shini','Manoj'],
      ['Mohit', 'Vis', 'Nusrath']]

我想在二维列表中找到最常见的元素。在上面的例子中,最常见的字符串是'Mohit'

我知道我可以通过两个 for 循环和一个字典来使用蛮力来执行此操作,但是使用 numpy 或任何其他库是否有更有效的方法?

嵌套列表可以有不同的长度

有人也可以添加他们方法的时间吗?找到禁食的方法。还有一些注意事项,它可能效率不高。

编辑

这些是我系统上不同方法的时间安排:

#timegb
%%timeit
collections.Counter(chain.from_iterable(arr)).most_common(1)[0][0]
5.91 µs ± 115 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

#Kevin Fang and Curious Mind
%%timeit
flat_list = [item for sublist in arr for item in sublist]
collections.Counter(flat_list).most_common(1)[0]
6.42 µs ± 501 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%%timeit
c = collections.Counter(item for sublist in arr for item in sublist).most_common(1)c[0][0]
6.79 µs ± 449 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

#Mayank Porwal
def most_common(lst):
    return max(set(lst), key=lst.count)
%%timeit
ls = list(chain.from_iterable(arr))
most_common(ls)
2.33 µs ± 42.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

#U9-Forward
%%timeit
l=[x for i in arr for x in i]
max(l,key=l.count)
2.6 µs ± 68.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Mayank Porwal 的方法在我的系统上运行速度最快。

【问题讨论】:

  • 您如何定义“频繁”、出现次数最多或出现在最多子列表/行中的次数?
  • 在整个二维数组中出现次数最多。
  • 对嵌套数组中元素数量 (n) 与嵌套数组数量 (m) 的任何限制。即 m >> n 或 n
  • @bigdata2 不是真的。 2D 列表不太可能很大。甚至是列表中的元素。
  • @MohitMotwani 时间有点取决于列表的长度和其中唯一元素的数量。 max(set... 解决方案对于具有很少唯一元素的列表来说很快

标签: python python-3.x list numpy numpy-ndarray


【解决方案1】:

我建议将二维数组展平,然后使用计数器找出最常见的元素。

flat_list = [item for sublist in arr for item in sublist]
from collections import Counter
Counter(flat_list).most_common(1)[0]
# ('Mohit', 3)
Counter(flat_list).most_common(1)[0][0]
# 'Mohit'

不确定这是否是最快的方法。

编辑:

@timgeb 的答案有一种更快的方法来使用itertools.chain 来展平列表

@schwobaseggl 建议的更节省空间的方式:

from collections import Counter
c = Counter(item for sublist in arr for item in sublist).most_common(1)
# [('Mohit', 3)]
c[0][0]
# 'Mohit'

【讨论】:

  • 您还可以通过使用嵌套生成器表达式而不是列表来更节省空间。而是将计数器存储在您需要的变量中,而您不需要列表。
  • @KevinFang 谢谢。这行得通。您还可以添加您的方法所花费的时间吗?检查最快的方法会更容易。
【解决方案2】:

类似这样的:

In [920]: from itertools import chain
In [923]: arr = list(chain.from_iterable(arr)) ## flatten into 1-D array
In [922]: def most_common(lst):
     ...:     return max(set(lst), key=lst.count)

In [924]: most_common(arr)
Out[924]: 'Mohit'

时间安排:

from itertools import chain
import time
start_time = time.time()

arr = [['Mohit', 'shini','Manoj','Mot'],
      ['Mohit', 'shini','Manoj'],
      ['Mohit', 'Vis', 'Nusrath']]


arr = list(chain.from_iterable(arr))
arr = arr*100

def most_common(lst):
    return max(set(lst), key=lst.count)

print(most_common(arr))
print("--- %s seconds ---" % (time.time() - start_time))

mayankp@mayank:~$ python t1.py 
Mohit
--- 0.000154972076416 seconds ---

【讨论】:

  • 谢谢。这行得通。您还可以添加您的方法所花费的时间吗?检查最快的方法会更容易。
  • @MohitMotwani 也编辑了时间。还要注意我的代码中的arr= arr*100
【解决方案3】:
  1. 使用itertools.chain.from_iterable 展平列表
  2. 申请Counter

演示:

>>> from itertools import chain
>>> from collections import Counter
>>> 
>>> lst = [['Mohit', 'shini','Manoj','Mot'],
...:      ['Mohit', 'shini','Manoj'],
...:      ['Mohit', 'Vis', 'Nusrath']]
...:      
>>> Counter(chain.from_iterable(lst)).most_common(1)[0][0]
'Mohit'

详情:

>>> list(chain.from_iterable(lst))
['Mohit',
 'shini',
 'Manoj',
 'Mot',
 'Mohit',
 'shini',
 'Manoj',
 'Mohit',
 'Vis',
 'Nusrath']
>>> Counter(chain.from_iterable(lst))
Counter({'Manoj': 2, 'Mohit': 3, 'Mot': 1, 'Nusrath': 1, 'Vis': 1, 'shini': 2})
>>> Counter(chain.from_iterable(lst)).most_common(1)
[('Mohit', 3)]

一些时间安排:

>>> lst = lst*100
>>> %timeit Counter(chain.from_iterable(lst)).most_common(1)[0][0] # timgeb
53.7 µs ± 411 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit max([x for i in lst for x in i], key=l.count) # U9-Forward
207 µs ± 389 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit Counter([x for sublist in lst for x in sublist]).most_common(1)[0][0] # Curious_Mind/Kevin Fang #1
75.2 µs ± 2.6 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit Counter(item for sublist in lst for item in sublist).most_common(1)[0][0] # Kevin Fang #2
95.2 µs ± 2.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit flat = list(chain.from_iterable(lst)); max(set(flat), key=flat.count) # Mayank Porwal
98.4 µs ± 178 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

(请注意,Kevin Fang 的第二个解决方案比第一个要慢一些,但内存效率更高。)

【讨论】:

  • 是的,看起来chainthis question 中最快的扁平化方法
  • @timegb 谢谢。这行得通。您还可以添加您的方法所花费的时间吗?检查最快的方法会更容易。
  • @MohitMotwani 所有计时都需要在同一台计算机上完成,因为只有这样它们才能具有可比性。我会在一分钟内做一些计时。
  • @timegb 非常感谢。谢谢
  • @MohitMotwani 抱歉,搞砸了一些时间...再次编辑
【解决方案4】:

这样做的一种方法,

import collections
import time
start_time = time.time()
arr = [['Mohit', 'shini','Manoj','Mot'],
      ['Mohit', 'shini','Manoj'],
      ['Mohit', 'Vis', 'Nusrath']]

c = collections.Counter([x for sublist in arr for x in sublist])
print(c.most_common(1) )
print("--- %s seconds ---" % (time.time() - start_time)) 

耗时: 0.00016713142395 秒

演示:http://tpcg.io/NH3zjm

【讨论】:

  • @Curios_Mind 谢谢。这行得通。您还可以添加您的方法所花费的时间吗?检查最快的方法会更容易。
  • @MohitMotwani 已编辑
【解决方案5】:

或者为什么不:

l=[x for i in arr for x in i]
max(l,key=l.count)

代码示例:

>>> arr = [['Mohit', 'shini','Manoj','Mot'],
      ['Mohit', 'shini','Manoj'],
      ['Mohit', 'Vis', 'Nusrath']]
>>> l=[x for i in arr for x in i]
>>> max(l,key=l.count)
'Mohit'
>>> 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-23
    • 2021-03-27
    • 2022-01-25
    • 2020-03-20
    • 2014-05-24
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多