2017-03-08 96 views
1

我想建立從結構正則表達式是這樣的:切片串在Python列表

[['mirna', 'or', 'microrna'], 'or', 'lala'] 

...我想提取的「或」遞歸構建我正則表達式的左側部分。 正如你所看到的,有時它是另一個嵌入列表,有時它是一個字符串。

我的正則表達式應該是這樣的:

((mirna|microrna)|lala) 

所以這是我的算法(遞歸的,因爲我從來不知道有多深,我的結構):

def _buildRegex(self, request): 
    if not isinstance(request, str): 
    print(request) 
    print('request not a str') 
    request = request[0] 
    for i, e in enumerate(request): 
    self._print(i) 
    self._print(e) 
    if e == 'or': 
     self._print('OR found') 
     if isinstance(request, str): 
     print('left is str') 
     left = request 
     else: 
     print('left is list') 
     left = request[0:i] 

     if isinstance(request, str): 
     print('right is str') 
     right = request 
     else: 
     print('right is list') 
     right = request[i+1:len(request)-1] 
     print('(') 

     if isinstance(left, list): 
     self._buildRegex(left) 
     else: 
     print(left) 
     print('|') 
     if isinstance(right, list): 
     self._buildRegex(right) 
     else: 
     print(left) 
     print(')') 

而這就是我得到:

[[['mirna', 'or', 'microrna'], 'or', 'lala']] 
    request not a str 
    0 
    ['mirna', 'or', 'microrna'] 
    1 
    or 
    OR found 
    left is list 
    right is list 
    (
    [['mirna', 'or', 'microrna']] 
    request not a str 
    0 
    mirna 
    1 
    or 
    OR found 
    left is list 
    right is list 
    (
    ['mirna'] 
    request not a str 
    0 
    m 
    1 
    i 
    2 
    r 
    3 
    n 
    4 
    a 
    | 
    [] 
    request not a str 

我想當我提取單個詞切片轉換成一個列表。 但是,我如何區分列表中的最後一個單詞? 我花了很多時間,找不到解決方案,我完全失去了。

回答

3

我覺得你的代碼中有相當多的問題(如不需要外包裝列表和分割字符串成列表),所以我在這裏重寫了它。你只需要在列表上遞歸,追加'|'爲'或',併爲所有其他情況附加字符串。

def buildRegex(request): 
    result = '(' 
    for x in request: 
     if not isinstance(x, str): 
      result += buildRegex(x) 
     elif x == 'or': 
      result += '|' 
     else: 
      result += x 

    result += ')' 
    return result 

inp = [['mirna', 'or', 'microrna'], 'or', 'lala'] 
print(buildRegex(inp)) 
inp = [['mirna', 'or', ['hello', 'or', 'microrna']], 'or', ['lala', 'or','lele']] 
print(buildRegex(inp)) 

輸出:

((mirna|microrna)|lala) 
((mirna|(hello|microrna))|(lala|lele)) 

編輯:下面是與列表理解只是爲了好玩版本。這是在思想上我看來不易閱讀:

def buildRegex(request): 
    return '(' + ''.join([buildRegex(x) if isinstance(x, list) else '|' if x == 'or' else x for x in request]) + ')' 

編輯:弗朗西斯科指出,(不知道爲什麼,他刪掉了他的評論),它可能是與result += re.escape(x)所以更換result += x,你可以使用的字符是個好主意「 |」直接在你的字符串中。

+0

Yo不客氣。對不起,我無法給你一個更徹底的細分你自己的代碼。 –

+0

@MillieSmith - 感謝我的輸入,所以我可以發現我的錯誤! – Crispin

+0

@ waterboy5281沒問題。 –

1

這似乎是爲我工作

def list_to_regex(input, final=''): 
    if isinstance(input, list): 
     if all([isinstance(x,str) for x in input]): 
      # pure list found 
      y = ''.join(['|' if z == 'or' else z for z in input]) 
      to_add = '(' + y + ')' 
      return to_add 
     else: 
      # mixed list 
      for el in input: 
       final += list_to_regex(el, final) 
      return '(' + final + ')' 
    else: 
     # just a string 
     if input == 'or': 
      return '|' 
     else: 
      return input 

用法示例:

l = [['mirna', 'or', ['hello', 'or', 'microrna']], 'or', ['lala', 'or','lele']] 
# ((mirna|(hello|microrna))|(lala|lele)) 
0

這是一種俗氣,我已經可以想到條紋的情況。如果你仔細想想,你的嵌套列表已經基本上是你想要的格式了,所以只要將它設爲一個字符串並做一些替換。

CODE:

data = [['mirna', 'or', 'microrna'], 'or', 'lala'] 
my_regex = str(data).replace(' ','').replace('[','(').replace(']',')').replace(",'or',",'|').replace("'",'').replace('"','') 
print('my_regex='+my_regex) 

它還與來自@Millie第二測試用例(感謝你使這一點!)

OUTPUT:

my_regex=((mirna|microrna)|lala) 
+0

這是一個偉大的的想法,但我會整合其他運營商,如'和'或'不',這似乎很難用這種方法做到這一點:) – emurb

+0

我其實認爲'和'會一樣容易。更難,是的,肯定會與其他答案一起去! – mitoRibo

+0

不應該刪除輸出中字符串的單引號嗎?我懷疑他想要那些正則表達式。 –

0

下面是對工作的代碼我,錯誤檢查:

def build_regex(req): 
    if (type(req) != list and type(req) != str): 
     print('Error: Incompatible types') 
     return -1 
    if type(req) == list and len(req) % 2 != 1: 
     print("Even length, missing an or somewhere") 
     return -1 

    if type(req) == str: 
     return req 
    if len(req) == 1: 
     return build_regex(req[0]) 
    if type(req[0]) == list: 
     return '(' + build_regex(req[0]) + '|' + build_regex(req[2:]) + ')' 
    if type(req[0]) == str: 
     return '(' + req[0] + '|' + build_regex(req[2:]) + ')' 

    print("Error: Incompatible element types.") 
    print("Required str or list, found " + type(req[0])) 
    return -1