2014-04-04 59 views
0

列表的結構元素的索引我有一個列表,看起來像這樣:獲取在Python

mylist = ['name','mem','g1','g2','g3','foo','bar','qux','zoo','name','mem','foo','bar','qux','zoo'] 

我們可以看到上面的字符串被分成兩個部分,由'name','mem'

界定什麼我想要做的是得到兩個列表,其中每個列表包含mylist中的foo...zoo索引。 結果在此

firstpart_vals_id = [5,6,7,8] 
secondpart_vals_id = [11,12,13,14] 

我該如何在Python中實現?

mylist中的所有內容都是固定的,但foo....zoo的數量可能會有所不同,但foo....zoo部分的長度和內容對於兩部分是相同的(對稱)。

更新:我嘗試使用正則表達式解決方案。

>>> from itertools import groupby 
>>> import re 
>>> mj = re.compile(r'^val(\d+)$') 
>>> mylist = ['name','mem','g1','g2','g3','val1','val2','val3','val4','name','mem','val1','val2','val3','val4'] 
>>> [[x[0] for x in g] for k, g in groupby(enumerate(mylist), key= lambda x: mj.search(x[1].mj)) if k] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in <lambda> 
AttributeError: 'str' object has no attribute 'mj' 
+0

你有15個字符串列表的結果。 – msvalkon

+0

g1,g2,g3怎麼樣,你怎麼區分它們和fo,bar等? –

+0

'g1,g2,g3'總是固定的。它永遠不會有任何其他的事情。 – pdubois

回答

4

您可以使用itertools.groupby

>>> from itertools import groupby 
>>> mylist = ['name','mem','g1','g2','g3','val1','val2','val3','valN','name','mem','val1','val2','val3','valN'] 
>>> [[x[0] for x in g] for k, g in groupby(
        enumerate(mylist), key= lambda x:x[1].startswith('val')) if k] 
[[5, 6, 7, 8], [11, 12, 13, 14]] 

請注意,這裏我用一個簡單的str.startswith狀態,如果需要,可以替換成正則表達式。

更新:

使用正則表達式:

import re 
mylist = ['name','mem','g1','g2','g3','val1','val2','val3','val1','name','mem','val1','val2','val3','val4'] 
mj = re.compile(r'^val\d+$') 
print [[x[0] for x in g] for k, g in groupby(
        enumerate(mylist), key=lambda x: bool(mj.search(x[1]))) if k] 

輸出:

[[5, 6, 7, 8], [11, 12, 13, 14]] 
+0

不,我不能使用'startswith('val')',實際上這可以是任何文本....讓我修改OP。 – pdubois

+0

如果您不喜歡'startswith'值,則可以使用任何其他表達式來爲您的字符串返回yes-no;包括正則表達式匹配。從你的問題中不清楚標準是什麼,所以我們必須猜測。 –

+0

如果我理解了這一點,它會將「vals」分解爲原來連續的塊,並忽略分隔符「name」和「mem」。如果原始列表是'[「val1」,「val2」,「既不是val-nor-delm」,「val3」,「val4」]',OP又想要什麼? –

1

您可以使用列表內涵做所需的基本步驟(映射和序列的過濾)。可能有幾種方法可以完成工作,下面的代碼是一種方式(N.B.我沒有測試過)。

# first find every occurence of "name", we just ignore "map". 
name_indices = [i for (i, s) in enumerate(mylist) if s == 'name'] 
name_indices.sort() # probably redunant, but we are going to rely on sorting later. 

# do something similar, but now we don't care about ordering so use a set. 
# you can use some other sequence type if you prefer. Of course we can use 
# any condition we choose. not just s.startswith() 
val_indices = set(i for (i, s) in enumerate(mylist) if s.startswith('val')) 


# we want to build a dictionary of Name index to all value indices following it. 
nv_map = {} 
for ni, ni_next in zip(name_indices[0:-1], indices[1:]): 
    # ni should be a name index, an ni_next should the next higher one. 
    # so insert all val_indices in that range into an element of nv_map 
    nv_map[ni] = set(i for i in val_indices if i >= ni and i < ni_next) 

因此我們預計nv_map

{ 
    0 : {5,6,7,8}, 
    9 : {11,12,13,14} 
}