2017-09-15 18 views
1

假設我有一個列表如何將唯一值的序號分配給Python中的列表?

A = ['A', 'A', 'A', 'B', 'B', 'C'] 

如何把它轉化爲

B = [0, 0, 0, 1, 1, 2] 

我寫了這樣

C = {t[1]:t[0] for t in enumerate(list(set(A)))} 
B = [C[e] for e in A] 

,它給了

[1, 1, 1, 2, 2, 0] 

即出現的順序隨機的,也是整個代碼看起來複雜。

有沒有更簡單的方法?

+2

套件未訂購。 –

+1

而不是'list(set(A))'(它以任意順序創建一個列表),使用'sorted(set(A))'。 – DeepSpace

+0

您示例中的「A」中的項目是否只是大寫字母?到目前爲止的答案取決於這是數據的準確表示。 – roganjosh

回答

1

你可以試一下討厭(雖然比你當前的代碼更易懂),如:

>>> B = [ord(x) - 65 for x in A] 
>>> B 
[0, 0, 0, 1, 1, 2] 

如果A是一個大名單,可以考慮讓B是一個發電機,像這樣:

B = (ord(x) - 65 for x in A) 
+0

字母只是例子。 – Dims

1
a = ['A', 'A', 'A', 'B', 'B', 'C'] 
x = sorted(set(a)) 
b = [x.index(y) for y in a] 
print(b) 
[0, 0, 0, 1, 1, 2] 
+0

對於長數組,這項工作會減慢嗎? – Dims

1

您想要按照唯一元素的字母順序或者它們首次出現在原始列表中的順序來確定順序嗎?例如,如果['C','A','A','A','B','B','C']變成[2,0,0,0,1,1,2] ,或[0,1,1,1,2,2,0]?如果是前者:

uniques = list(set(A)) 
uniques.sort() 
uniques_dict = {uniques[i]:i for i in range(len(uniques))} 
B = [uniques_dict[a] for a in A] 

後者:

uniques_dict = {} 
ordinal = 0 
for a in A: 
    if not (a in uniques_dict.keys): 
    uniques_dict[a] = ordinal 
    ordinal = ordinal+1 
B = [uniques_dict[a] for a in A] 
0

好像構建字典/映射是關鍵,使用它將是一個主題的變化。即使構建字典也會是一個主題的變體 - 在讀者眼中是否更好/更差/簡單/複雜。

>>> import itertools 
>>> ordinatates = itertools.count(0) 
>>> a = ['a', 'b', 'c', 'a', 'a', 'c', 'c'] 
>>> unique = sorted(set(a)) 
>>> d = {thing:ordinal for thing, ordinal in zip(unique, ordinates)} 

應用它

>>> list(map(d.get, a)) 
[0, 1, 2, 0, 0, 2, 2] 
>>> 

它會拋出的KeyException如果在a不在d項目。

相似,同樣的警告:

>>> import operator 
>>> a = ['a','b','c', 'a', 'a', 'c','c'] 
>>> m = map(operator.itemgetter, a) 
>>> [get(d) for get in m] 
[0, 1, 2, 0, 0, 2, 2] 
>>> 

類似無警告

class Foo(dict): 
    def __call__(self, item): 
     '''Returns self[item] or None.''' 
     try: 
      return self[item] 
     except KeyError as e: 
      # print or log something descriptive - print(repr(e)) 
      return None 

>>> ordinates = itertools.count(0) 
>>> a = ['a','b','c', 'a', 'a', 'c','c'] 
>>> unique = sorted(set(a)) 
>>> d = Foo((thing,ordinal) for thing, ordinal in zip(unique, ordinates)) 
>>> result = list(map(d, a)) 
>>> result 
[0, 1, 2, 0, 0, 2, 2] 
>>> 

所有這一切假設你想要的分類項的序號位置 - 爲你的榜樣名單是方便pre -sorted。如果您正在尋找在一個獨特的東西第一次發生在列表中的位置,構建這樣的映射:

import itertools 
ordinal = itertools.count() 
b = ['c','b','c', 'a', 'a', 'c','c'] 
d = {} 
for thing in b: 
    if thing in d: 
     continue 
    d[thing] = next(ordinal) 

應用

>>> list(map(d.get, b)) 
[0, 1, 0, 2, 2, 0, 0] 
>>> 

@Abdou提到這在他的評論,但你沒方便回答。

如果您有可寫爲

d = {} 
d.update((thing,d[thing] if thing in d else next(ordinal)) for thing in b) 
0

一個班輪神物我會假設:1,你不依賴於要素是字母; 2.你想在列表A的第一次出現的基礎上爲它們編制索引。

>>> A = ['A', 'A', 'A', 'B', 'B', 'C'] 
>>> seen=set() 
>>> C={x:len(seen)-1 for x in A if not (x in seen or seen.add(x))} 
>>> C 
{'B': 1, 'C': 2, 'A': 0} 
>>> list(map(C.get, A)) 
[0, 0, 0, 1, 1, 2] 

第二行定義了一組,seen,將保存我們已經看到下一行的列表理解的A的元素。

第三行定義了將唯一元素映射到其索引的dictioanry。這有點棘手(雖然不是很不尋常)。

我們遍歷A的值。

  • 情況1:值x是看到的那樣,從而x in seen or ...True,第二部分不評估,和not(...)False返回:x被忽略。

  • 情況2:該值是x看到不,從而x in seenFalse和第二部分進行評價。提醒seen.add將始終返回None,在這種情況下相當於Falsex in seen or seen.add(x)False,但x已被添加到seen。並且not(...)返回Truex被映射到seen的len,對於每個新元素增加1。

第六行簡單地映射新定義的字典的A值。

相關問題