2017-04-14 46 views
4

我想根據值將列表映射到數字。更優雅的方法根據值爲列表編號

例如:

['aa', 'b', 'b', 'c', 'aa', 'b', 'a'] -> [0, 1, 1, 2, 0, 1, 3] 

我試圖通過使用numpy的和映射字典來實現這一目標。

def number(lst): 
    x = np.array(lst) 
    unique_names = list(np.unique(x)) 
    mapping = dict(zip(unique_names, range(len(unique_names)))) # Translating dict 
    map_func = np.vectorize(lambda name: d[name]) 
    return map_func(x) 

有沒有更優雅/更快的方式來做到這一點?

更新:獎金問題 - 與維護的訂單一起做。

+1

[轉換字母至數在Python]可能的複製(http://stackoverflow.com/questions/4528982/convert-alphabet-letters-to-number-in-蟒蛇) –

+0

他們不一定是字母......我的意思是一般情況 – blancmange

+1

但你似乎也希望保持秩序看預期的樣品輸出,這是不是用func編號實現的,對吧? – Divakar

回答

1

使用裝置刪除重複:

myList = ['a', 'b', 'b', 'c', 'a', 'b'] 
mySet = set(myList) 

然後建立你的字典使用的理解:

mappingDict = {letter:number for number,letter in enumerate(mySet)} 
+1

請注意,套件沒有保證訂單,所以這不一定會映射 - > 0,b - > 1等。 – jonrsharpe

+0

謝謝。我認爲np.unique可能會更快,但事實並非如此。 – blancmange

+0

你仍然可以通過安裝一個python包來安裝一個有序集https://pypi.python.org/pypi/orderedset –

2

可以使用return_inverse關鍵字:

x = np.array(['aa', 'b', 'b', 'c', 'aa', 'b', 'a']) 
uniq, map_ = np.unique(x, return_inverse=True) 
map_ 
# array([1, 2, 2, 3, 1, 2, 0]) 

編輯:保序版本:

x = np.array(['aa', 'b', 'b', 'c', 'aa', 'b', 'a']) 
uniq, idx, map_ = np.unique(x, return_index=True, return_inverse=True) 
mxi = idx.max()+1 
mask = np.zeros((mxi,), bool) 
mask[idx] = True 
oidx = np.where(mask)[0] 
iidx = np.empty_like(oidx) 
iidx[map_[oidx]] = np.arange(oidx.size) 
iidx[map_] 
# array([0, 1, 1, 2, 0, 1, 3]) 
+0

我做同樣的事情,'map_'打印爲'array([1,2,3, 1,2,0])' – kmario23

+0

@kmario輸入列表似乎在OP中發生了變化... –

0

我做了它使用ASCII值,因爲它很容易和簡短。

def number(list): 
    return map(lambda x: ord(x)-97,list) 
l=['a', 'b', 'b', 'c', 'a', 'b'] 
print number(l) 

輸出:

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

+0

請向我展示一般情況下的解決方案,但不限於字母。 – blancmange

+0

那時你的問題是不同的,所以我認爲這只是字母表。我正在努力。 –

0

如果訂單是不是一個問題:

[sorted(set(x)).index(item) for item in x] 

# returns: 
[1, 2, 2, 3, 1, 2, 0] 
+0

不是最好的解決方案,但我認爲它不值得投票。 –

2

這裏的矢量化的基於NumPy的解決方案 -

def argsort_unique(idx): 
    # Original idea : http://stackoverflow.com/a/41242285/3293881 by @Andras 
    n = idx.size 
    sidx = np.empty(n,dtype=int) 
    sidx[idx] = np.arange(n) 
    return sidx 

def map_uniquetags_keep_order(a): 
    arr = np.asarray(a) 

    sidx = np.argsort(arr) 
    s_arr = arr[sidx] 

    m = np.concatenate(([True], s_arr[1:] != s_arr[:-1])) 
    unq = s_arr[m] 
    tags = np.searchsorted(unq, arr) 
    rev_idx = argsort_unique(sidx[np.searchsorted(s_arr, unq)].argsort()) 
    return rev_idx[tags] 

採樣運行 -

In [169]: a = ['aa', 'b', 'b', 'c', 'aa', 'b', 'a'] # String input 

In [170]: map_uniquetags_keep_order(a) 
Out[170]: array([0, 1, 1, 2, 0, 1, 3]) 

In [175]: a = [4, 7, 7, 5, 4, 7, 2]     # Numeric input 

In [176]: map_uniquetags_keep_order(a) 
Out[176]: array([0, 1, 1, 2, 0, 1, 3])