[英]Replace items in a list with unique items starting from 0
Let's say I have a list like this: 假设我有一个这样的列表:
Y=[1018, 1018, 1011, 1012, 1013, 1014, 1019, 1019, 1017]
What's the most pythonic way to replace each number with 更换每个数字的最佳方式是什么?
So that the list becomes: 这样列表变成:
Y=[0, 0, 1, 2, 3, 4, 5, 5, 6]
It's not important that first element is 0, but there must be a unique maximal matching (= assignment) between the two lists of numbers, ie also this is a good solution: 第一个元素为0并不重要,但两个数字列表之间必须存在唯一的最大匹配(=赋值),即这也是一个很好的解决方案:
Y=[3, 3, 4, 0, 2, 5, 6, 6, 1]
EDIT: what I tried is a for loop using find, my solution is very ugly, I know there is better way to do it, it's not relevant how bad I did it :D 编辑:我尝试的是使用find的for循环,我的解决方案非常难看,我知道有更好的方法来做到这一点,这与我做得有多糟糕无关:D
The first idea that comes to mind is to convert the values to a set()
and enumerate()
them, store the pairs in a dict, and use a mapping list comprehension to create the new list: 想到的第一个想法是将值转换为
set()
和enumerate()
它们,将对存储在dict中,并使用映射列表理解来创建新列表:
>>> Y=[1018, 1018, 1011, 1012, 1013, 1014, 1019, 1019, 1017]
>>> mapping={v:k for k,v in enumerate(set(Y))}
>>> Y1=[mapping[y] for y in Y]
>>> Y1
[5, 5, 0, 1, 2, 3, 6, 6, 4]
You can also use a defaultdict
with itertools.count
, eg: 您还可以在
itertools.count
使用defaultdict
,例如:
from collections import defaultdict
from itertools import count
dd = defaultdict(lambda c=count(): next(c))
Y=[1018, 1018, 1011, 1012, 1013, 1014, 1019, 1019, 1017]
mapped = [dd[el] for el in Y]
# [0, 0, 1, 2, 3, 4, 5, 5, 6]
How this works is that a defaultdict
will return the value for an existing key but where that key doesn't exist, it will assign the key to a default value - in this case that value is the next number in sequence. 这是如何工作的,
defaultdict
将返回现有键的值,但该键不存在的位置,它将键分配给默认值 - 在这种情况下,该值是序列中的下一个数字。
Here's what I typically use. 这是我通常使用的。 The core logic is basically the same as what @JonClements wrote.
核心逻辑与@JonClements编写的内容基本相同。
#!/usr/bin/env python3
# mypy static typing annotations
from typing import Dict, Generic, List, TypeVar
T = TypeVar('T')
class Interner(Generic[T]):
def __init__(self):
self._values = [] # type: List[T]
self._keys = {} # type: Dict[T, int]
def intern(self, val: T) -> int:
idx = self._keys.setdefault(val, len(self._keys))
if idx == len(self._values):
self._values.append(val)
return idx
def unintern(self, idx: int) -> T:
return self._values[idx]
pass
def main():
data = [1018, 1018, 1011, 1012, 1013, 1014, 1019, 1019, 1017]
pool = Interner() # type: Interner[int]
return [pool.intern(i) for i in data]
if __name__ == '__main__':
print(main())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.