迭代字符串数组

时间:2018-03-19 14:46:28

标签: python arrays

我正在使用python中的一个转换器,我的代码的一个功能是找到某些符号并在它们周围放置空格,以便以后更容易解析。

这是最初放置在字符周围空格的代码

def InsertSpaces(string):
    to_return = list(string)

    for i, char in enumerate(to_return):
        if char == '?' or char == '#' or char == '@':
            to_return[i] = (to_return[i] + ' ')[::-1]
            to_return[i] += ' '

    print(''.join(to_return))

虽然这有效,但它造成了一个烦人的问题

它在换行符之后创建了空格,这可能会导致以后出现问题并且只是丑陋。

所以这个:

'@0x0D?0A\n@0x1f?@0x2f?48#65#6C#6C#6F#2C#20#57#6F#72#6C#64#21'

成为这个:

 ' @ 0x0D ? 0A
  @ 0x1f ?  @ 0x2f ? 48 # 65 # 6C # 6C # 6F # 2C # 20 # 57 # 6F # 72 # 6C # 64 # 21'

(请记住,这会将字符串拆分为列表)

所以我写了这个来检测列表中的换行符,之后我会删除空格。

for char in to_return:
    char_next = to_return[to_return.index(char) + 1]
    if (char + char_next) == '':
        print('found a newline')

问题是它没有检测到任何换行符。

打印你可以看到换行符的字符对,但是代码找不到它,因为它变成了一个新行,我认为它不能用简单的字符串读取。

 @ 0
0x
x0
0x
D ? 
 ? 0
0x
A


 @ 
 @ 0
0x
x0
1f
f ? 
 ? 0
 @ 0
0x
x0
2f
f ? 
 ? 0
48
8 # 
 # 6
65
5 # 
 # 6
65
C # 
 # 6
65
C # 
 # 6
65
F # 
 # 6
2f
C # 
 # 6
2f
0x
 # 6
5 # 
7 # 
 # 6
65
F # 
 # 6
7 # 
2f
 # 6
65
C # 
 # 6
65
48
 # 6
2f
1f

有没有办法在迭代字符串列表时检测换行符?

4 个答案:

答案 0 :(得分:2)

首先,这是一段奇怪的代码:

to_return[i] = (to_return[i] + ' ')[::-1]

to_return[i]是一个字符长,所以这一行等同于:

to_return[i] = ' ' + to_return[i]

其次,如果您只是尝试使用空格填充所有'?','#'和'@',为什么不尝试简单替换:

def InsertSpaces(string):
  return string.replace("?"," ? ").replace("#", " # ").replace("@", " @ ")

如果使用re(正则表达式)模块,则更短:

def InsertSpace(string):
  return re.sub("(#|\?|@)",r" \1 ", string)

答案 1 :(得分:1)

迭代当前的char和下一个char并使用'\n'

for char, char_next in zip(to_return, to_return[1:]):
    if char + char_next == '\n ':
        print('found a newline')

答案 2 :(得分:1)

这是一种修改函数以解决问题而无需正则表达式的方法。

在每次迭代中检查前一个或下一个字符是否为新行。在这些情况下,请勿添加空格:

def InsertSpaces(s):
    to_return = []

    for i, char in enumerate(s):
        if char in {'?', '#', '@'}:
            val = ' ' if ((i-1) > 0) and s[i-1] != '\n' else ''
            val += char
            val += ' ' if ((i+1) < len(s)) and s[i+1] != '\n' else ''
        else:
            val = char
        to_return.append(val)

    return ''.join(to_return)

s = '@0x0D?0A\n@0x1f?@0x2f?48#65#6C#6C#6F#2C#20#57#6F#72#6C#'
print(repr(InsertSpaces(s)))
#'@ 0x0D ? 0A\n@ 0x1f ?  @ 0x2f ? 48 # 65 # 6C # 6C # 6F # 2C # 20 # 57 # 6F # 72 # 6C #'

关键是这一部分:

val = ' ' if ((i-1) > 0) and s[i-1] != '\n' else ''        #1
val += char                                                #2
val += ' ' if ((i+1) < len(s)) and s[i+1] != '\n' else ''  #3
  • 第1行:根据条件将' '''添加到字符串的开头。我们检查以前的字符s[i-1]是否不是换行符\n。我们还必须检查索引是否为((i-1) > 0
  • 第2行:始终添加当前char
  • 第3行:与第1行类似的逻辑,但请检查下一个字符,并确保您不在字符串的末尾。

如果特殊字符位于字符串的末尾(或在开头),这也将添加空格。如果您希望这种情况发生,您必须稍微修改条件。

我做了其他一些改动:

  • 重命名了输入变量s,因为string是类
  • 的名称
  • to_return初始化为一个空列表,该列表将附加到enumerate(s)(而不是to_return),因为当您修改正在迭代的对象时可能会发生错误的事情
  • 使用in {set}代替单独检查所有字符

答案 3 :(得分:1)

你不必扫描&#34;对于换行符,只要您在当前字符之前或之后存在不是空格的字符时添加空格。

我不认为可以用一个正则表达式完成,但有两个你可以在需要的地方添加空格。它需要两个 lookbehinds / lookaheads,因为有两个条件:

  1. @#?之前/之后必须至少有一个字符;
  2. 一定不能换行。
  3. 我为了一致性添加了第三个条件:

    1. ..此角色不得为空格。
    2. 因此,当已经存在空间时,不会添加空间。 (这只是一个方便的补充,因为\S碰巧匹配&#34;所有不像空格的东西&#34;。)

      为什么你需要两个lookbehinds?因为如果有一个角色(不能是类似空格),其中一个将匹配,而如果有一个角色,则另一个将匹配,而不是&#34;换行符,包括字符串本身的开头和结尾。

      以下代码,稍微修改一下输入字符串以显示它在边缘情况下的作用,

      import re
      
      str = '@0x0D?0A\n@0x1f?@0x2f?48# 65#6C#6C#6F#2C#20#57#6F#72#6C#64#21@'
      
      str = re.sub(r'(?<=\S)(?<!\n)([@?#])', r' \1', str)
      str = re.sub(r'([@?#])(?!\n)(?=\S)', r'\1 ', str)
      print ('"'+str+'"')
      

      结果

      "@ 0x0D ? 0A
      @ 0x1f ? @ 0x2f ? 48 # 65 # 6C # 6C # 6F # 2C # 20 # 57 # 6F # 72 # 6C # 64 # 21 @"
      

      其中双引号仅添加到显示结果字符串的开头和结尾。