一种复杂的 Python 处理列表或数组的方法



我想连续地为列表中的连续相同元素分配一个整数值。不应该有反向耦合,即列表中后面出现的相同元素不应具有与以前相同的整数值。

初始列表:

x = ["a", "a", "a", "b", "b", "c", "c", "a", "a", "d", "d", "d", "b", "b", "b", "a", "a"]

所需的整数列表:

y = [0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6]

我的尝试:

idx = 0
int_list = list([idx])
for i in range(1, len(x)):
if x[i] != x[i-1]:
idx = idx + 1
int_list.append(idx)

但是,我认为有一种更优雅的方式。甚至可能是两行

你可以使用itertools.groupby来解决这个问题非常简单

a= ["a", "a", "a", "b", "b", "c", "c", "a", "a", "d", "d", "d", "b", "b", "b", "a", "a"]
b = []
for i,(key,group) in enumerate(itertools.groupby(a)):
# key is the repeated value ... group is an iterator of all matches
b.extend([i for _ in group])
print(b)
# [0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6]

正如@jonclements在评论中指出的那样,我们可以将其简化为单个列表理解

b = [i for i,(k,g) in enumerate(groupby(a)) for _ in g]

>Joran的回答对列表很好。如果性能很重要并且您不介意使用 NumPy,并且您正在处理数值或可以映射到数值的东西(例如arr = list(map(ord, x))(,您可以使用以下内容:

>>> np.cumsum(np.diff(arr) != 0)
array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6])

您还可以使用 zip 函数创建一个滚动窗口,并循环访问每对值,如果它们不相等,则返回 True。结果是此数组的累积总和。我使用NumPy的cumsum((,但你也可以自己写。

>>> list(np.cumsum([m!=n for m,n in zip([x[0]]+x[:-1], x)]))
[0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6]

最新更新