另一个大写字符串解决方案的每个奇数字符


问题内容

我刚开始学习Python并为自己创建了一些我要解决的任务…

因此,我在有关使用字符串的章节中(通过索引访问字符串,进行更改等)。

我的任务是-
将字符串的每个奇数大写。我在这里看到了解决方案:在Python字符串中大写其他所有字母?

但我不喜欢…想通过片式解决。所以我产生的是followig代码:

T = 'somesampletexthere'  
R=""

for i in range(0, len(T[1::2])):
        R+=T[::2][i].upper()+T[1::2][i].lower()

print R

当字符数为偶数时(例如与TESTTEXT一起使用时),此代码非常有用,但是当数字为奇数时(如Example中的示例),它将跳过最后一个字符(在这种情况下为E)

这是因为范围一直到len(T[1::2]))(偶数字符的长度),但是如果我尝试奇数字符的长度,len(T[::2]))则会出错:

IndexError: string index out of range

从逻辑上讲,因为奇数字符数将始终大于1(对于具有奇数个字符的文本)。

所以,我的问题是-我该如何抑制错误?因此,如果索引超出给定字符串的范围,Python只会返回null或其他内容?

还是使用切片的任务的其他解决方案?


问题答案:

与链接问题中的解决方案相比,您更倾向于使用切片解决方案。(OTOH,这是一个稍微不同的问题,因为它会跳过空格)。但是,您当前的代码效率很低,因为它在循环的每次迭代中都会重新创建T[::2]T[1::2]切片for。同样,调用.upper.lower使用单个字符比调用较大的字符串效率低。

这是使用切片执行此操作的有效方法。

T = 'somesampletexthere'
R = [''] * len(T)
R[::2], R[1::2] = T[::2].upper(), T[1::2].lower()
R = ''.join(R)
print(R)

输出

SoMeSaMpLeTeXtHeRe

如果我们将这些分配拆分到,可能会帮助您了解发生了什么R

T = 'somesampletexthere'
R = [''] * len(T)
R[::2] = T[::2].upper()
print(R)
R[1::2] = T[1::2].lower()
print(R)
R = ''.join(R)
print(R)

输出

['S', '', 'M', '', 'S', '', 'M', '', 'L', '', 'T', '', 'X', '', 'H', '', 'R', '']
['S', 'o', 'M', 'e', 'S', 'a', 'M', 'p', 'L', 'e', 'T', 'e', 'X', 't', 'H', 'e', 'R', 'e']
SoMeSaMpLeTeXtHeRe

我们可以按以下任一顺序进行切片分配:

T = 'somesampletexthere'
R = [''] * len(T)
R[1::2] = T[1::2].lower()
print(R)
R[::2] = T[::2].upper()
print(R)
R = ''.join(R)
print(R)

输出

['', 'o', '', 'e', '', 'a', '', 'p', '', 'e', '', 'e', '', 't', '', 'e', '', 'e']
['S', 'o', 'M', 'e', 'S', 'a', 'M', 'p', 'L', 'e', 'T', 'e', 'X', 't', 'H', 'e', 'R', 'e']
SoMeSaMpLeTeXtHeRe

只是为了好玩,这是将大写和小写字符串压缩在一起的另一种策略。我们使用izip_longest(或zip_longest在Python
3中)以便处理长度奇数的字符串。

from itertools import izip_longest

T = 'somesampletexthere'
R = ''.join([c for t in izip_longest(T[::2].upper(), T[1::2].lower(), fillvalue='') for c in t])
print(R)

尽管此版本可以在一行中完成,但我更喜欢第一个版本:我发现它更具可读性,并且可能更快一些。