Python3:中间数字字符串到右数字字符串

Python3: Midnumeral Strings to Rightnumeral Strings

我的尝试:

m = str(input())
# m = list(m)
w = ""
r = ""
num = [int(i) for i in m.split() if i.isdigit()] 
for c in range(0,len(m)-1):
    if m[len(m)-1]:
        for num in w:
            if num.isnumeric():
                w.remove(num)
                num.join(r)
    elif m[c].isalpha():
        r.join(m[c])
    elif m[c].isnumeric() and (len(w)==0 or w[c]=='('):
        w.join(m[c])
    elif len(num)!=0:
        try:
            if int(m[c])>int(w[c]):
                w.join(m[c])
            else:
                n = [int(i) for i in w.split() if i.isdigit()]
                if len(n)!=0:
                    r = ''.join([str(elem) for elem in w]) 
        except:
            continue
    elif m[c]==')':
        for number in m:
            if number.isnumeric():
                w+=number
            elif number=='(':
                m.remove('(')
                m.remove(')')
                break
    elif (w[c]=='(') or ((int(w[c]))<(int(m[c]))) or (w=""): # In this statement it gives an invalid syntax error
        w = m[c]
    else:
        break
        
print(r)

我想知道为什么在第 34 行(elif 语句)出现无效语法。 另外,想知道有没有更好的办法解决这个问题。

谢谢


问题:

中间数字字符串到右数字字符串

中间数字字符串是一个字符串,在字母之间包含一个数字。例如,a1b2c 是中间数字字符串。中间数字字符串可以包含字母 a 到 z、数字 1 到 9 以及左右括号。

右数字串是一个可以由中间数字串组成的字符串: (i) 中间数字串中除左括号和右括号外的所有字符都出现在右数字串中。 (ii) 中间数字串中字母“a”和“b”之间的数字“n”将以特定方式出现在右边数字串中字母“a”和“b”的右侧。 (iii)中间数字串转换为右数字串的过程中,使用了等待流。

给定一个中间数字字符串“m”,它可以转换为右数字字符串“r”,如下所示:

i. 逐个字符处理中数字串‘m’.

ii. 当看到一个字母时,将其添加到右边的数字字符串“r”中。

iii. 当看到数字 'n' 且等待流为空或最近添加到等待流的字符是左括号时,然后将 'n' 添加到等待流

iv.如果看到一个数字'n'并且等待流中有一些数字那么,如果等待流中最近添加的数字小于'n'那么将'n'添加到等待流,否则从最近到最不最近处理等待流:-从等待流中删除数字并将其添加到'r'

重复第(i)部分,直到等待流中可用的最近值小于'n'或者等待流左括号最近的字符或者等待流变为空

v. 将‘n’添加到等待流

vi. 如果看到左括号,则将其添加到等待流

vii. 当看到右括号时,从等待流中删除从最近到最不最近的所有数字,并将其添加到 r 直到看到左括号。舍弃左右括号

viii. 当到达中间数字 'm' 字符串的末尾时,从等待流中删除从最近到最不最近的所有数字,并将其添加到右侧数字字符串 'r '

例如

a1b2c 将是 abc21

a2b1c 将是 ab2c1

(a1b)2c 将是 ab1c2

a1b4(c5d2e)7f 将是 abcd5e2f741

注意:中间数字中的所有字符将不同,只给出有效输入

输入格式

第一行包含中间数字字符串,m

输出格式

第一行应包含正确的数字字符串,r


.1 语法错误

很简单,缺少一个'='符号,所以把它改成这个

elif (w[c]=='(') or ((int(w[c]))<(int(m[c]))) or (w==""):
        w = m[c]
    else:
        break

.2 代码改进和最佳实践

我建议您为此 post Code Review 上的答案,因为这是为了这个。错误很少,没有遵循最佳做法。

例如,这个错误块:

       try:
            if int(m[c])>int(w[c]):
                w.join(m[c])
            else:
                n = [int(i) for i in w.split() if i.isdigit()]
                if len(n)!=0:
                    r = ''.join([str(elem) for elem in w]) 
        except:
            continue

except 捕获了太多类型的错误,最好是:

       try:
          if int(m[c])>int(w[c]):
              w.join(m[c])
          else:
              n = [int(i) for i in w.split() if i.isdigit()]
              if len(n)!=0:
                  r = ''.join([str(elem) for elem in w]) 
        except ValueError:
            continue

查看 Should I always specify an exception type in except statements? 了解更多相关信息。该 try 块中的 'logic' 也太多了。但为了简单起见,没关系。



编辑

考虑

  1. 请注意,我使用了不同的集合组合 ( accepted_numbers, accepted_chars, left_parenthesis, right_parenthesis) 而不是其他列表,这是因为集合在用于查找时速度超快,更多信息 --> Time complexity of python set operations?。而且也很清楚你想用它们做什么。

  2. 变量 r 是在算法期间将其用作 ListThen 的更好决定一个字符串,那是因为它更容易操作。

  3. 我什至没有使用 1 try except 块,这是因为,很清楚要做什么,我的意思是我们提前知道了,所以你可以用一个if else 块,除了我上面提到的关于 Try 块的内容外,另一个重要方面是如果发现和异常(在这段代码中它甚至无关紧要)会减慢代码速度,请看这里 try-except vs If in Python

  4. 您 post 编辑的算法问题使用并要求 Stack 作为集合,您可以在中看到它的实现process_waiting_stream() 函数 以 LIFO (last in, first out) 的方式。

process_waiting_stream()

回答测试一个案例

m = '(a1b)2c'  # test string Added on the top as requested in the exercise 
import string  # If you don't want to import string, just hard code the letters


m = m
r = []

# ----- CONSTANTS
accepted_numbers = {str(i) for i in range(1, 10)}  # 1 to 9
accepted_chars = {*string.ascii_lowercase}
left_parenthesis = '('
right_parenthesis = ')'
parenthesis = {left_parenthesis, right_parenthesis}
midnumeral_string  = accepted_numbers | accepted_chars | parenthesis


#  ---- NOTE: Run a quick check is Input is Correct |!(a1b)2c or (a1b)0c is not good
for char in m:
    if char in midnumeral_string:
        pass
    else:
        print('Input String is not a Midnumeral string')
        continue
# ---------------------------
WAITING_STREAM = []
r = [] # Use a list, not a string, easier to work with :) 

def process_waiting_stream():
    global WAITING_STREAM

    if WAITING_STREAM:
        WAITING_STREAM.reverse() # LIFO  from most recent to least recent
        while True:
            if not WAITING_STREAM:
                break
            item = WAITING_STREAM[0]
            if item == left_parenthesis:
                    break      
            elif item in accepted_numbers:
                item = WAITING_STREAM.pop(0)
                r.append(item)
        WAITING_STREAM.reverse() 

def checK_stream(): # NOTE: We check this in case there is only '(' and not a num
    return any([item in accepted_numbers for item in WAITING_STREAM])



for char in m:
    if WAITING_STREAM:
        recently_added = WAITING_STREAM[-1]
    
    if char in accepted_chars:  
        r.append(char)            
    elif char in accepted_numbers:   

        if not WAITING_STREAM or recently_added == left_parenthesis:
            WAITING_STREAM.append(char)                    

        elif checK_stream(): 
            if (recently_added not in parenthesis 
                and recently_added not in accepted_chars) and int(recently_added) < int(char):
                WAITING_STREAM.append(char)
            else:
                process_waiting_stream() 
                WAITING_STREAM.append(char)
        else:
            WAITING_STREAM.append(char)

    elif char == left_parenthesis:
        WAITING_STREAM.append(char)

    elif char == right_parenthesis:
        process_waiting_stream()

   
for item in WAITING_STREAM:
    if item == left_parenthesis:
        left_para = WAITING_STREAM.index(left_parenthesis)
        WAITING_STREAM.pop(left_para)
        break

process_waiting_stream()        

r = ''.join(r)
print(r)

答案 2

测试所有案例

import string  # If you don't want to import string, just hard code the letters

def rightnumeral_string(m):

    # ----- CONSTANTS
    accepted_numbers = {str(i) for i in range(1, 10)}  # 1 to 9
    accepted_chars = {*string.ascii_lowercase}
    left_parenthesis = '('
    right_parenthesis = ')'
    parenthesis = {left_parenthesis, right_parenthesis}
    midnumeral_string  = accepted_numbers | accepted_chars | parenthesis


    #  ---- NOTE: Run a quick check is Input is Correct |!(a1b)2c or (a1b)0c is not good
    for char in m:
        if char in midnumeral_string:
            pass
        else:
            print('Input String is not a Midnumeral string')
            continue
    # ---------------------------
    WAITING_STREAM = []
    r = [] # Use a list, not a string, easier to work with :) 

    def process_waiting_stream():
        nonlocal WAITING_STREAM

        if WAITING_STREAM:
            WAITING_STREAM.reverse() # LIFO  from most recent to least recent
            while True:
                if not WAITING_STREAM:
                    break
                item = WAITING_STREAM[0]
                if item == left_parenthesis:
                        break      
                elif item in accepted_numbers:
                    item = WAITING_STREAM.pop(0)
                    r.append(item)
            WAITING_STREAM.reverse() 
    
    def checK_stream(): # NOTE: We check this in case there is only '(' and not a num
        return any([item in accepted_numbers for item in WAITING_STREAM])


    # ------ Iterate Through each Character (number included) in the string
    for char in m:

        if WAITING_STREAM:  
            recently_added = WAITING_STREAM[-1]  
        if char in accepted_chars:  
            r.append(char)            
        elif char in accepted_numbers:   

            if not WAITING_STREAM or recently_added == left_parenthesis:
                WAITING_STREAM.append(char)                    

            elif checK_stream(): # Check if there are currently nums in stream
                if (recently_added not in parenthesis 
                    and recently_added not in accepted_chars) and int(recently_added) < int(char):
                    WAITING_STREAM.append(char)
                else:
                    process_waiting_stream() 
                    WAITING_STREAM.append(char)
            else:
                WAITING_STREAM.append(char)

        elif char == left_parenthesis:
            WAITING_STREAM.append(char)

        elif char == right_parenthesis:
            process_waiting_stream()

    # Last Step is to Remove left_parenthesis
    for item in WAITING_STREAM:
        if item == left_parenthesis:
            left_para = WAITING_STREAM.index(left_parenthesis)
            WAITING_STREAM.pop(left_para)
            break
    
    process_waiting_stream()        

    r = ''.join(r)
    return r

print(rightnumeral_string('a1b2c'))
print(rightnumeral_string('a2b1c'))
print(rightnumeral_string('(a1b)2c'))
print(rightnumeral_string('a1b4(c5d2e)7f'))

# Checking if the Answer Are correct
assert rightnumeral_string('a1b2c') == 'abc21'
assert rightnumeral_string('a2b1c') == 'ab2c1'
assert rightnumeral_string('(a1b)2c') == 'ab1c2'
assert rightnumeral_string('a1b4(c5d2e)7f') == 'abcd5e2f741'

文档

  • string
  • Iterating each character in a string using Python
  • What is the use of “assert” in Python?