使用另一个列表计算一个元素的出现次数时有什么更快的方法

What faster way is there when counting occurrences of elements in one using another list

如果我有两个列表,List_AList_B 如果我想从 [=11= 计算 List_B 中每个元素出现的次数,有什么更快的方法] 并在新的 List_C 中解析结果? 通常我使用列表理解,但是一旦 List_AList_B 中的元素数量增加到 100 000 以上,它就会开始花费大量时间。

List_A = ['a', 'd','f','h','g','e','f','a','f','h','h','d','b','c','c','a']

List_B = ['a', 'b','c','d','e','f','g','h']

List_C = [List_A.count(x) for x in List_B]

List_C

#Output:

#List_C = [3, 1, 2, 2, 1, 3, 1, 3]

使用您的解决方案,您执行的计算数量等于 len(List_A) * len(List_B)(您的列表理解)。

相反,首先计算出现的次数,然后进行列表理解:

List_A = ['a', 'd','f','h','g','e','f','a','f','h','h','d','b','c','c','a']
List_B = ['a', 'b','c','d','e','f','g','h']
occ = dict()
for x in List_A:
    occ.setdefault(x, 0)
    occ[x] += 1
List_C = [occ.get(x, 0) for x in List_B]

通过这种方式你遍历了List_A一次和List_B一次。

[编辑]

更新了最后一行的列表理解以解决 x 不在 List_A 中的情况(参见@AchilleG 的评论)

def a():
    List_A = ['a', 'd','f','h','g','e','f','a','f','h','h','d','b','c','c','a']
    List_B = ['a', 'b','c','d','e','f','g','h', 'z']

    count = Counter(List_A)
    List_C = [count.get(x) for x in List_B]

100000 次循环,5 次循环中的最佳次数:每次循环 2.96 微秒


使用 Counter() 并检查 None:

def b():
    List_A = ['a', 'd','f','h','g','e','f','a','f','h','h','d','b','c','c','a']
    List_B = ['a', 'b','c','d','e','f','g','h', 'z']

    count = Counter(List_A)

    List_C = []

    for x in List_B:
        val = count.get(x)
        if val != None:
            List_C.append(val)

100000 次循环,5 次循环中的最佳次数:每次循环 3.45 微秒


不检查 None 值:

def c():
    List_A = ['a', 'd','f','h','g','e','f','a','f','h','h','d','b','c','c','a']
    List_B = ['a', 'b','c','d','e','f','g','h', 'z']

    count = Counter(List_A)

    List_C = []

    for x in List_B:
        List_C.append(count.get(x))

100000 次循环,5 次循环中的最佳次数:每次循环 3.04 微秒


使用@Mafa 的解决方案,如果 List_B 具有未出现在 List_A 中的值,则该解决方案不起作用:

def d():
    List_A = ['a', 'd','f','h','g','e','f','a','f','h','h','d','b','c','c','a']
    List_B = ['a', 'b','c','d','e','f','g','h']
    occ = dict()
    for x in List_A:
        occ.setdefault(x, 0)
        occ[x] += 1
    List_C = [occ[x] for x in List_B]

100000 次循环,5 次循环中的最佳次数:每次 2.59 微秒


Mafa 检查现有值的解决方案:

def e():
    List_A = ['a', 'd','f','h','g','e','f','a','f','h','h','d','b','c','c','a']
    List_B = ['a', 'b','c','d','e','f','g','h']
    occ = dict()
    for x in List_A:
        occ.setdefault(x, 0)
        occ[x] += 1
    List_C = [occ.get(x, 0) for x in List_B]

100000 次循环,5 次循环中的最佳次数:每次循环 3.1 微秒


接下来的两个功能由@Alex Waygood 提出

def f():
    List_A = ['a', 'd','f','h','g','e','f','a','f','h','h','d','b','c','c','a']
    List_B = ['a', 'b','c','d','e','f','g','h']
    c = Counter(filter(set(List_B).__contains__, List_A))
    List_C = [v for k, v in sorted(c.items())]

50000 次循环,5 次循环中的最佳次数:每次循环 4.45 微秒


def g():
    List_A = ['a', 'd','f','h','g','e','f','a','f','h','h','d','b','c','c','a']
    List_B = ['a', 'b','c','d','e','f','g','h', 'z']
    c = Counter(filter(List_B.__contains__, List_A))
    List_C = [v for k, v in sorted(c.items())]

50000 次循环,5 次循环中的最佳次数:每次循环 4.78 微秒

(不确定这里是否需要除以二——显然不需要——,因为有 50000 个循环而不是 100000 个循环,如果是这样的话我们在这里有明显的赢家)