簡體   English   中英

如何使用正則表達式使用 Python 按字母順序查找字符串?

[英]How can I use Regex to find a string of characters in alphabetical order using Python?

所以我遇到了一個挑戰 - 在字符串中找到最長的字母字符字符串。 例如,“abcghiijkyxz”應該導致“ghiijk”(是的,i 加倍了)。

我一直在用循環來解決這個問題——迭代整個字符串,然后對每個字符,使用lower和ord開始第二個循環。 無需幫助編寫該循環。

但是,有人建議我使用 Regex 來處理這類事情。 我的正則表達式很弱(我知道如何獲取靜態集,我的前瞻知識擴展到知道它們存在)。 我將如何編寫一個正則表達式來展望未來,並按字母順序檢查未來的字符? 還是建議使用 Regex 對此類事情不切實際?

編輯:普遍的共識似乎是正則表達式對於這類事情確實很糟糕。

只是為了說明為什么正則表達式是不是這樣的事情實用,這里是一個正則表達式,將匹配ghiijk在你給出的例子abcghiijkyxz 請注意,它還會匹配abcyxz因為從技術上講,它們應該被視為按順序排列的最長字母字符串。 不幸的是,您無法單獨使用正則表達式確定哪個最長,但這確實為您提供了所有可能性。 請注意,此正則表達式適用於 PCRE,不適用於 python 的re模塊! 另請注意, python 的regex庫當前不支持(*ACCEPT) 雖然我還沒有測試過, pyre2 包(使用 Cython 的谷歌 re2 pyre2 的 python 包裝器)聲稱它支持(*ACCEPT)控制動詞,所以目前使用 python可能是可能的。

請參閱此處使用的正則表達式

((?:a+(?(?!b)(*ACCEPT))|b+(?(?!c)(*ACCEPT))|c+(?(?!d)(*ACCEPT))|d+(?(?!e)(*ACCEPT))|e+(?(?!f)(*ACCEPT))|f+(?(?!g)(*ACCEPT))|g+(?(?!h)(*ACCEPT))|h+(?(?!i)(*ACCEPT))|i+(?(?!j)(*ACCEPT))|j+(?(?!k)(*ACCEPT))|k+(?(?!l)(*ACCEPT))|l+(?(?!m)(*ACCEPT))|m+(?(?!n)(*ACCEPT))|n+(?(?!o)(*ACCEPT))|o+(?(?!p)(*ACCEPT))|p+(?(?!q)(*ACCEPT))|q+(?(?!r)(*ACCEPT))|r+(?(?!s)(*ACCEPT))|s+(?(?!t)(*ACCEPT))|t+(?(?!u)(*ACCEPT))|u+(?(?!v)(*ACCEPT))|v+(?(?!w)(*ACCEPT))|w+(?(?!x)(*ACCEPT))|x+(?(?!y)(*ACCEPT))|y+(?(?!z)(*ACCEPT))|z+(?(?!$)(*ACCEPT)))+)

結果是:

abc
ghiijk
y
x
z

單個選項的解釋,即a+(?(?!b)(*ACCEPT))

  • a+匹配a (字面意思)一次或多次。 這會捕獲幾個相同字符按順序排列的實例,例如aa
  • (?(?!b)(*ACCEPT)) If 子句評估條件。
    • (?!b) if 子句的條件。 負前瞻確保接下來的不是b 這是因為如果不是b ,我們希望下面的控制動詞生效。
    • (*ACCEPT)如果滿足條件(以上),我們接受當前的解決方案。 此控制動詞使正則表達式成功結束,跳過模式的其余部分。 由於此標記位於捕獲組內,因此只有該捕獲組在該特定位置成功結束,而父模式繼續執行。

那么如果條件不滿足會發生什么? 嗯,這意味着(?!b)評估為假。 這意味着后面的字符實際上是b ,因此我們允許匹配(在這種情況下是捕獲)繼續。 請注意,整個模式都包含在(?:)+ ,這允許我們匹配連續的選項,直到遇到(*ACCEPT)控制動詞或行尾。

整個正則表達式的唯一例外是z 由於它是英文字母表中的最后一個字符(我認為這是這個問題的目標),我們不關心后面是什么,所以我們可以簡單地輸入z+(?(?!$)(*ACCEPT)) ,這將確保在z之后沒有任何匹配。 相反,如果您想要匹配za (圓形字母順序匹配 - idk,如果這是正確的術語,但對我來說聽起來很正確),您可以使用z+(?(?!a)(*ACCEPT)))+如所見在這里

如前所述,正則表達式不是最好的工具。 由於您對連續序列感興趣,您可以使用單個 for 循環來執行此操作:

def LNDS(s):
    start = 0
    cur_len = 1
    max_len = 1
    for i in range(1,len(s)):
        if ord(s[i]) in (ord(s[i-1]), ord(s[i-1])+1):
            cur_len += 1
        else:
            if cur_len > max_len:
                max_len = cur_len
                start = i - cur_len
            cur_len = 1
    if cur_len > max_len:
        max_len = cur_len
        start = len(s) - cur_len
    return s[start:start+max_len]

>>> LNDS('abcghiijkyxz')
'ghiijk'

我們保持了我們看到的非遞減字符的總數,當非遞減序列結束時,我們將它與我們之前看到的最長非遞減序列進行比較,如果它更長,則更新我們的“迄今為止最好看的” .

生成所有正則表達式子串,如 ^a+b+c+$(最長到最短)。 然后將每個正則表達式與“abcghiijkyxz”的所有子字符串(最長到最短)進行匹配,並在第一個匹配處停止。

def all_substrings(s):
    n = len(s)
    for i in xrange(n, 0, -1):
        for j in xrange(n - i + 1):
            yield s[j:j + i]

def longest_alphabetical_substring(s):
    for t in all_substrings("abcdefghijklmnopqrstuvwxyz"):
        r = re.compile("^" + "".join(map(lambda x: x + "+", t)) + "$")
        for u in all_substrings(s):
            if r.match(u):
                return u

print longest_alphabetical_substring("abcghiijkyxz")

打印“ghiijk”。

正則表達式char+表示a+b+c+...

細節:

  • +匹配一次和無限次

蟒蛇代碼

import re

def LNDS(text):
    array = []

    for y in range(97, 122):  # a - z
        st = r"%s+" % chr(y)
        for x in range(y+1, 123):  # b - z
            st += r"%s+" % chr(x)
            match = re.findall(st, text)

            if match:
                array.append(max(match, key=len))
            else:
                break

        if array:
            array = [max(array, key=len)]

    return array

輸出

print(LNDS('abababababab abc')) >>> ['abc']
print(LNDS('abcghiijkyxz')) >>> ['ghiijk']

對於字符串abcghiijkyxz正則表達式模式:

a+b+                    i+j+k+l+
a+b+c+                  j+k+
a+b+c+d+                j+k+l+
b+c+                    k+l+
b+c+d+                  l+m+
c+d+                    m+n+
d+e+                    n+o+
e+f+                    o+p+
f+g+                    p+q+
g+h+                    q+r+
g+h+i+                  r+s+
g+h+i+j+                s+t+
g+h+i+j+k+              t+u+
g+h+i+j+k+l+            u+v+
h+i+                    v+w+
h+i+j+                  w+x+
h+i+j+k+                x+y+
h+i+j+k+l+              y+z+
i+j+
i+j+k+

代碼演示

要真正“解決”問題,您可以使用

string = 'abcxyzghiijkl'

def sort_longest(string):
    stack = []; result = [];

    for idx, char in enumerate(string):
        c = ord(char)
        if idx == 0:
            # initialize our stack
            stack.append((char, c))
        elif idx == len(string) - 1:
            result.append(stack)
        elif c == stack[-1][1] or c == stack[-1][1] + 1:
            # compare it to the item before (a tuple)
            stack.append((char, c))
        else:
            # append the stack to the overall result
            # and reinitialize the stack
            result.append(stack)
            stack = []
            stack.append((char, c))

    return ["".join(item[0]
        for item in sublst) 
        for sublst in sorted(result, key=len, reverse=True)]

print(sort_longest(string))

哪個產量

['ghiijk', 'abc', 'xyz']

在這個例子中。


這個想法是循環遍歷字符串並跟蹤使用ord()由您的要求填充的stack變量。

使用正則表達式真的很容易!

(在此處使用尾隨上下文)

rexp=re.compile(
    "".join(['(?:(?=.' + chr(ord(x)+1) + ')'+ x +')?'
            for x in "abcdefghijklmnopqrstuvwxyz"])
    +'[a-z]')

a = 'bcabhhjabjjbckjkjabckkjdefghiklmn90'

re.findall(rexp, a)

#Answer: ['bc', 'ab', 'h', 'h', 'j', 'ab', 'j', 'j', 'bc', 'k', 'jk', 'j', 'abc', 'k', 'k', 'j', 'defghi', 'klmn']

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM