我有一个字符串的名字,在这个例子中是“markus johansson”。
我正在尝试编写一个使'm'和'j'成为大写的程序:
name = "markus johansson"
for i in range(1, len(name)):
if name[0] == 'm':
name[0] = "M"
if name[i] == " ":
count = name[i] + 1
if count == 'j':
name[count] = 'J'
我很确定这应该可行,但它给了我这个错误:
File "main.py", line 5 in <module>
name[0] = "M"
TypeError: 'str' object does support item assignment
我知道有一个名为.title()的库函数,但我想做“真正的编程”。
我该如何解决这个问题?
答案 0 :(得分:9)
我想你想要达到的目标是:
from string import capwords
capwords(name)
哪个收益率:
'Markus Johansson'
编辑:好的,我看到你要打开一扇敞开的门。
这是低级别的实施。
''.join([char.upper() if prev==' ' else char for char,prev in zip(name,' '+name)])
答案 1 :(得分:9)
>>> "markus johansson".title()
'Markus Johansson'
内置字符串方法是可行的方法。
编辑: 我看到你想要重新发明轮子。任何特殊原因? 您可以选择任意数量的复杂方法,例如:
' '.join(j[0].upper()+j[1:] for j in "markus johansson".split())
标准图书馆仍然是可行的方法。
答案 2 :(得分:5)
string.capwords()
(在string.py
中定义)# Capitalize the words in a string, e.g. " aBc dEf " -> "Abc Def".
def capwords(s, sep=None):
"""capwords(s, [sep]) -> string
Split the argument into words using split, capitalize each
word using capitalize, and join the capitalized words using
join. Note that this replaces runs of whitespace characters by
a single space.
"""
return (sep or ' ').join(x.capitalize() for x in s.split(sep))
str.title()
(在stringobject.c
中定义)PyDoc_STRVAR(title__doc__,
"S.title() -> string\n\
\n\
Return a titlecased version of S, i.e. words start with uppercase\n\
characters, all remaining cased characters have lowercase.");
static PyObject*
string_title(PyStringObject *self)
{
char *s = PyString_AS_STRING(self), *s_new;
Py_ssize_t i, n = PyString_GET_SIZE(self);
int previous_is_cased = 0;
PyObject *newobj = PyString_FromStringAndSize(NULL, n);
if (newobj == NULL)
return NULL;
s_new = PyString_AsString(newobj);
for (i = 0; i < n; i++) {
int c = Py_CHARMASK(*s++);
if (islower(c)) {
if (!previous_is_cased)
c = toupper(c);
previous_is_cased = 1;
} else if (isupper(c)) {
if (previous_is_cased)
c = tolower(c);
previous_is_cased = 1;
} else
previous_is_cased = 0;
*s_new++ = c;
}
return newobj;
}
纯Python中的str.title()
class String(str):
def title(self):
s = []
previous_is_cased = False
for c in self:
if c.islower():
if not previous_is_cased:
c = c.upper()
previous_is_cased = True
elif c.isupper():
if previous_is_cased:
c = c.lower()
previous_is_cased = True
else:
previous_is_cased = False
s.append(c)
return ''.join(s)
示例:
>>> s = ' aBc dEf '
>>> import string
>>> string.capwords(s)
'Abc Def'
>>> s.title()
' Abc Def '
>>> s
' aBc dEf '
>>> String(s).title()
' Abc Def '
>>> String(s).title() == s.title()
True
答案 3 :(得分:4)
字符串是不可变的。它们无法改变。您必须使用更改的内容创建新字符串。 如果你想让每个'j'大写:
def make_uppercase_j(char):
if char == 'j':
return 'J'
else:
return char
name = "markus johansson"
''.join(make_uppercase_j(c) for c in name)
答案 4 :(得分:1)
如果我正确理解您的原始算法,这就是您想要做的:
namn = list("markus johansson")
if namn[0] == 'm':
namn[0] = "M"
count = 0
for i in range(1, len(namn)):
if namn[i] == " ":
count = i + 1
if count and namn[count] == 'j':
namn[count] = 'J'
print ''.join(namn)
当然,有一百万种更好的方式(“想要”方式)来做你想做的事情,就像vartec的回答所示。 :)
目前,您的代码仅适用于以J和M开头的名字,分别代表名字和姓氏。
答案 5 :(得分:1)
很多好的建议,所以我会在公司里加上我自己的2美分: - )
我假设你想要一些更通用的东西,它不仅可以处理以'm'和'j'开头的名字。您可能还想考虑带连字符的名称(如Markus Johnson-Smith),它们也在连字符后面有上限。
from string import lowercase, uppercase
name = 'markus johnson-smith'
state = 0
title_name = []
for c in name:
if c in lowercase and not state:
c = uppercase[lowercase.index(c)]
state = 1
elif c in [' ', '-']:
state = 0
else:
state = 1 # might already be uppercase
title_name.append(c)
print ''.join(title_name)
最后的警告是非ascii字符的潜力。在这种情况下,使用uppercase
模块的lowercase
和string
属性是很好的,因为它们的内容会根据用户的语言环境而变化(即:依赖于系统,或者当locale.setlocale()叫做)。我知道您希望避免使用upper()
进行此练习,这非常简洁......作为一个FYI,upper()
也使用由locale
控制的setlocale()
,所以使用uppercase
和lowercase
的做法很好地利用了API而没有太高级别。也就是说,如果您需要在运行英语语言环境的系统上处理法语名称,则需要更强大的实现。
答案 6 :(得分:1)
如果您正在寻找更通用的名称解决方案,您还应该看一下以下示例:
名称的某些部分也不应以大写字母开头,例如:
所以,如果您正在考虑创建一个更通用的解决方案,请记住所有这些小事。
(这将是运行测试驱动开发的理想场所,具有您的方法/功能必须遵循的所有条件)。
答案 7 :(得分:0)
“真正的编程”?
我会使用.title(),我是一个真正的程序员。
或者我会使用正则表达式
re.sub(r"(^|\s)[a-z]", lambda m: m.group(0).upper(), "this is a set of words")
这表示“如果文本的开头或空白字符后面跟着小写字母”(英文 - 可能不支持其他语言),那么对于每个匹配,将匹配文本转换为大写。由于匹配文本是空格和小写字母,因此工作正常。
如果您希望它作为低级代码,则以下方法有效。这里我只允许空格作为分隔符(但您可能需要支持换行符和其他字符)。另一方面,“string.lowercase”是国际化的,所以如果你在另一个语言环境中,那么它在大多数情况下仍然可以工作。如果您不想这样,那么请使用string.ascii_lowercase。
import string
def title(s):
# Capitalize the first character
if s[:1] in string.lowercase:
s = s[0].upper() + s[1:]
# Find spaces
offset = 0
while 1:
offset = s.find(" ", offset)
# Reached the end of the string or the
# last character is a space
if offset == -1 or offset == len(s)-1:
break
if s[offset+1:offset+2] in string.lowercase:
# Is it followed by a lower-case letter?
s = s[:offset+1] + s[offset+1].upper() + s[offset+2:]
# Skip the space and the letter
offset += 2
else:
# Nope, so start searching for the next space
offset += 1
return s
详细说明我对这个答案的评论,这个问题只能是出于好奇心的考虑。真实姓名有特殊的大写规则:“Johannes Diderik van der Waals”中的“van der”永远不会被大写,“Farrah Fawcett-Majors”拥有“M”,而“CathalÓhEochaidh”使用非ASCIIÓ和h ,将“Eochaidh”修改为“Eochaidh的孙子”。
答案 8 :(得分:0)
import { Component, OnInit, Input } from '@angular/core';
import { DailyBatches } from './newinter';
@Component({
selector: 'child2',
template: `
<table>
<tr *ngFor="let dbatch of data2">
<td>{{dbatch.batch}}</td>
</tr>
</table>
`
})
export class Child2Component implements OnInit {
@Input() data2:DailyBatches[];
constructor() { }
ngOnInit() {
}
}