使用嵌套的for循环和if语句将字符替换为整数

时间:2018-08-26 13:13:08

标签: python string for-loop

我需要输出任何重复的字符以引用前一个字符。

例如:a(-1)rdv(-4)(-4)khel(-1)o

到目前为止,这是我的代码:

text= 'aardvark'
i=0
j=0
for i in range(len(text)-1):
    for j in range(i+1, len(text)):
        if text[j]==text[i]:
            sub= text[j]
            val2=text.find(sub, i+1, len(text))
            p=val2+1
            val=str(i-j)
            text= text[:val2] + val + text[p:] 
            break
print(text)

输出:a-1rdva-4k

第二个'a'无法识别。而且我不确定如何在我的印刷品中加入括号。

2 个答案:

答案 0 :(得分:4)

每次找到反向引用时,通过就地更新文本,您会破坏索引(每次文本都会变长),并且您永远不会正确处理最后一个字符。当发现“当前”字符的第一个重复时,您停止进行检查,因此永远不会处理第三个a。这适用于输入字符串中的每个第3次重复。另外,如果您输入的文本包含任何-个字符或数字,它们最终也将根据您在其之前插入的-offset个引用进行测试!

对于您的aardvark的特定示例(一个包含8个字符的字符串),会发生以下情况:

  • 您找到第二个a并将text设置为a-1rdvark。现在,该文本的长度为9个字符,因此将永远不会检查最后一个r(您最多可以循环到i = 6);如果您的测试字符串以双字母结尾,这将是一个问题。您会跳出循环,因此j for循环永远不会出现在第三个a上,第二个a已经无法测试被替换。

  • 您的代码先找到-(不重复),1(不重复)然后是r(重复一次),所以现在您将text替换为a-1rdva-4k。现在您有一个由10个字符组成的字符串,因此-4将永远不会进行测试。不再是大问题了,但是如果字符串的最后3个位置重复出现该怎么办?

为输出构建一个 new 对象(添加您之前未看到的字母和反向引用)。这样,您就不会使循环的文字变大,而您将继续发现重复的文字。对于括号,可以使用更多的字符串连接。您需要先扫描字符串的 i部分,然后再扫描,然后倒退!测试i - 1i - 2等,直到0。自然地,这意味着i循环应该达到全长:

output = ''

for i in range(len(text)):
    current = text[i]
    for j in range(i - 1, -1, -1):
        if text[j] == current:
            current = '(' + str(j - i) + ')'
            break  
    output = output + current

print(output)

我在此处将修复程序保持在最低水平,但理想情况下,我还会进行一些更改:

  • 将所有已处理的字符和引用添加到新的 list 而不是字符串中,然后使用str.join()将该列表加入输出。这比每次迭代重建字符串都要有效。

  • 使用两个循环意味着您在循环遍历文本时再次检查字符串中的每个字符,因此算法所采取的步骤数随输入长度的增加而呈指数增长。在《计算机科学》中,我们讨论算法的时间复杂度,而您的算法是O(N ^ 2)(N平方)指数算法。包含1000个字母的文本最多需要处理一百万步!您可以使用 dictionary 来跟踪看到的字母的索引,而不用循环次数。如果字典中有 current 字符,则可以轻松计算出偏移量。字典查找需要恒定的时间(O(1)),从而使整个算法花费的时间是 linear 时间(O(N)),这意味着该过程花费的时间与输入字符串的长度成正比

  • 使用enumerate()向循环添加一个计数器,这样您就可以直接循环字符,而无需使用range()

  • 您可以使用字符串格式来构建"(<offset>)"字符串; Python 3.6和更高版本具有formatted string literals,其中f'...'字符串采用{}占位符,它们只是表达式。 f'({some - calculation + or * other})' will execute the expression and put the result in a string that hasandcharacters in it too. For earlier Python versions, you can use the [ str.format()method](https://docs.python.org/3/library/stdtypes.html#str.format) to get the same result; the syntax then becomes'({})'。format(某些-计算+或*其他)`。

放在一起,将变成:

def add_backrefs(text):
    output = []
    seen = {}
    for i, character in enumerate(text):
        if character in seen:
            # add a back-reference, we have seen this already
            output.append(f'({seen[character] - i})')
        else:
            # add the literal character instead
            output.append(character)
        # record the position of this character for later reference
        seen[character] = i
    return ''.join(output)

演示:

>>> add_backrefs('aardvark')
'a(-1)rdv(-4)(-4)k'
>>> add_backrefs('hello')
'hel(-1)o'

答案 1 :(得分:0)

text= 'aardvark'
d={}  # create a dictionary to keep track of index of element last seen at
new_text=''  # new text to be generated
for i in range(len(text)):  # iterate in text from index 0 up to length of text
    c = text[i]  # storing a character in temporary element as used frequently 
    if c not in d:  # check if character which is explored is visited before or not
        d[c] = i  # if character visited first time then just add index value of it in dictionary
        new_text += c  # concatenate character to result text
    else:  # visiting alreaady visited character
        new_text += '({0})'.format(d[c]-i)  # used string formatting which will print value of difference of last seen repeated character with current index instead of {0}
        d[c] = i  # change last seen character index
print(new_text)

输出:

a(-1)rdv(-4)(-4)k