HOWTO · Python

如何在 Python 列表中计算唯一值

计算 Python 列表中的唯一值

本页内容

统计 Python 列表中唯一值的一种简单方法是 len(set(values)),只要列表中的元素都可哈希即可使用,例如数字、字符串,以及元素全部可哈希的元组。如果还需要知道每个值出现了多少次,collections.Counter 可以在一次遍历中给出不同值的数量及各值的出现频率;如果数据已经存储在 NumPy 数组中,numpy.unique 则很合适。本文将介绍这三种方法,并说明如何选择。

使用 set() 统计唯一值

内置的 set() 函数会将列表转换为集合,而集合中的每个不同值只保留一次。将结果传给 len(),无需额外导入即可得到唯一值的数量。

运行以下示例。示例中的代码和显示的标签或输出保留英文:

本节中的代码以及显示的标签或输出仍为英文。

values = [1, 2, 2, 3, 4, 4, 5]
unique_values = set(values)

print(len(unique_values))

输出:

本示例显示的代码和输出保留英文。

5

set(values) 会去掉重复的 2 和 4,随后 len() 会报告剩余元素的数量。输入元素必须可哈希;如果列表包含其他列表或字典等元素,Python 会报告 TypeError。还要注意,集合不会保留列表的原始顺序,因此它能回答“有多少个”,却不能说明“哪个先出现”。如果需要按首次出现的顺序获取唯一值,可以改用 list(dict.fromkeys(values));它的长度仍是不同值的数量。

使用 collections.Counter 统计唯一值

collections.Counter 是一种类似字典的类,用于统计可迭代对象中每个元素出现的次数。如果想同时得到不同值的数量和每个值的出现频率,它就是合适的工具。

示例中的代码和显示的标签或输出保留英文。

本节中的代码以及显示的标签或输出仍为英文。

from collections import Counter

values = ["apple", "banana", "apple", "orange", "banana", "kiwi"]
counter = Counter(values)

print(len(counter))
print(dict(counter))

输出:

本示例显示的代码和输出保留英文。

4
{'apple': 2, 'banana': 2, 'orange': 1, 'kiwi': 1}

counter 会将每个值映射到它出现的次数,因此 len(counter) 统计的是不同键的数量——在这个列表中是四个。对计数器进行索引,例如 counter["apple"],可以得到某个值的出现次数;counter.most_common(1) 会返回出现次数最多的元素。与 set() 一样,collections.Counter 适用于可哈希元素,并且属于标准库。

使用 NumPy 统计唯一值

NumPy 是一个第三方软件包,可通过 pip install numpy 安装。它的 numpy.unique 函数会返回类数组输入中排序后的唯一值。结果的大小就是不同值的数量;传入 return_counts=True,还可以同时得到每个值出现的次数。

运行以下示例。示例中的代码和显示的标签或输出保留英文:

本节中的代码以及显示的标签或输出仍为英文。

import numpy as np

values = np.array([1, 2, 2, 3, 4, 4, 5])
unique_values, counts = np.unique(values, return_counts=True)

print(len(unique_values))
for value, count in zip(unique_values, counts):
    print(value, count)

输出:

本示例显示的代码和输出保留英文。

5
1 1
2 2
3 1
4 2
5 1

这里,unique_values 按排序顺序保存五个不同的数字,counts 则记录每个数字出现的次数——2 和 4 各出现两次。由于 numpy.unique 会对结果排序,因此它也适合需要按顺序获取不同值的任务。如果数据已经存放在 NumPy 数组中,或项目已经依赖 NumPy,可以使用这种方法;对于普通 Python 列表,set() 方法无需增加额外依赖。

选择合适的方法

这三种方法得到的不同值数量相同,因此应根据输入数据以及你还需要哪些信息来选择:

  • 如果只需要统计不同的可哈希元素,并希望使用最简短且仅依赖标准库的方案,请使用 set()。
  • 如果还需要每个值的出现频率、出现次数最多的元素,或其他逐值统计结果,请使用 collections.Counter。
  • 如果数据已经是 NumPy 数组,或需要排序后的唯一值,请使用 numpy.unique;若还需要各值的频率,可传入 return_counts=True。

无论选择哪种方法,关键都在于你还需要哪些额外信息:各值的频率、排序后的结果,还是避免增加额外依赖。至于不同值的数量,这三种方法都能以相同的方式给出结果。