2013-10-07 38 views
2

我有兩個列表,其中有相同數量的元素,都是字符串。這些字符串是相同的集合,但在每個列表中以不同的順序排列,沒有重複。查找列表中的字符串索引

list_a = ['s1', 's2', 's3', 's4', 's5', ...] 
list_b = ['s8', 's5', 's1', 's9', 's3', ...] 

我需要經過的每個元素在list_a並找到list_b包含相同元素的索引。我能做到這一點有兩個嵌套的循環,但必須有一個更好/更有效的方式:

b_indexes = [] 
for elem_a in list_a: 
    for indx_b, elem_b in enumerate(list_b): 
     if elem_b == elem_a: 
      b_indexes.append(indx_b) 
      break 
+0

是否有重複? – TerryA

+0

沒有重複,對不起。 – Gabriel

+0

不,這很好:) – TerryA

回答

4

如果沒有重複的,你可以用list.index()

list_a = ['s1', 's2', 's3', 's4', 's5'] 
list_b = ['s8', 's5', 's1', 's9', 's3'] 
print [list_b.index(i) for i in list_a] 

你只需要使用一個for循環,因爲你已經說過list_a中的字符串也出現在list_b中,所以不需要去遍歷第二個列表。

+0

非常好,非常感謝! – Gabriel

+0

@ Gabriel沒問題:) – TerryA

2

這應該會給你一個索引列表。

[list_b.index(elem) for elem in list_a] 
3

在函數式:

map(list_b.index, list_a) 

列表將製造含有在list_a每個元素的list_b索引。

+0

現在我不知道選哪一個。這種方式推薦Haidro的方式嗎? – Gabriel

+0

@Gabriel要麼沒事。這完全一樣。 'map()'可能會快一點,但是列表理解更具可讀性,您可以使用條件和東西(當然,您可以通過添加一個自定義函數來使用'map()',但它只是稍微不整潔) – TerryA

+0

@Gabriel哦,如果你使用Python 3,'map()'會返回一個生成器,而列表理解將返回一個列表(儘管把'[]'改成'()'會使它是一個生成器表達式:) – TerryA

1

index方法的另一種方法是在一次傳遞中構建一個位置字典,而不是每次都搜索整個列表。如果列表足夠長,這應該會更快,因爲它使得過程在元素數量(平均)上是線性的,而不是二次的。具體而言,而不是

def index_method(la, lb): 
    return [lb.index(i) for i in la] 

你可以使用

def dict_method(la, lb): 
    where = {v: i for i,v in enumerate(lb)} 
    return [where[i] for i in la] 

這應該是小名​​單大致相若,雖然也許有點慢:

>>> list_a = ['s{}'.format(i) for i in range(5)] 
>>> list_b = list_a[:] 
>>> random.shuffle(list_b) 
>>> %timeit index_method(list_a, list_b) 
1000000 loops, best of 3: 1.86 µs per loop 
>>> %timeit dict_method(list_a, list_b) 
1000000 loops, best of 3: 1.93 µs per loop 

但它應該是多少在更長的時間更快,差異將會增大:

>>> list_a = ['s{}'.format(i) for i in range(100)] 
>>> list_b = list_a[:] 
>>> random.shuffle(list_b) 
>>> %timeit index_method(list_a, list_b) 
10000 loops, best of 3: 140 µs per loop 
>>> %timeit dict_method(list_a, list_b) 
10000 loops, best of 3: 20.9 µs per loop