我有一份指数清单,例如,
a = [
[2],
[0, 1, 3, 2],
[1],
[0, 3]
]
Run Code Online (Sandbox Code Playgroud)
我现在想"反转"这个名单:数字0出现在索引1和3,所以:
b = [
[1, 3],
[1, 2],
[0, 1],
[1, 3]
]
Run Code Online (Sandbox Code Playgroud)
关于如何快速做到这一点的任何提示?(我正在处理的列表可能很大.)
额外奖励:我知道每个索引都会出现两次a(就像上面的例子一样).
使用字典收集反向索引,用于enumerate()生成a条目的索引:
inverted = {}
for index, numbers in enumerate(a):
for number in numbers:
inverted.setdefault(number, []).append(index)
b = [inverted.get(i, []) for i in range(max(inverted) + 1)]
Run Code Online (Sandbox Code Playgroud)
字典为您提供了有效的随机访问以添加反转,但这确实意味着您需要考虑反转中可能缺少的索引,因此range(max(inverted))循环以确保涵盖0和最大值之间的所有索引.
演示:
>>> a = [
... [2],
... [0, 1, 3, 2],
... [1],
... [0, 3]
... ]
>>> inverted = {}
>>> for index, numbers in enumerate(a):
... for number in numbers:
... inverted.setdefault(number, []).append(index)
...
>>> [inverted.get(i, []) for i in range(max(inverted) + 1)]
[[1, 3], [1, 2], [0, 1], [1, 3]]
Run Code Online (Sandbox Code Playgroud)
此代码不依赖于每个数字恰好出现两次的事实.它也非常简单,避免了构建字典然后从那里复制结果的开销:
a = [
[2],
[0, 1, 3, 2],
[1],
[0, 3]
]
b = []
for i, nums in enumerate(a):
# For each number found at this index
for num in nums:
# If needed, extend b to cover the new needed range
b += [[] for _ in range(num + 1 - len(b)]
# Store the index
b[num].append(i)
print(b)
# Output:
# [[1, 3], [1, 2], [0, 1], [1, 3]]
Run Code Online (Sandbox Code Playgroud)