问题标题 - 在Python中包装一个字符串

时间:2009-03-04 09:24:35

标签: python string uppercase

我有一个字符串的名字,在这个例子中是“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()的库函数,但我想做“真正的编程”。

我该如何解决这个问题?

9 个答案:

答案 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模块的lowercasestring属性是很好的,因为它们的内容会根据用户的语言环境而变化(即:依赖于系统,或者当locale.setlocale()叫做)。我知道您希望避免使用upper()进行此练习,这非常简洁......作为一个FYI,upper()也使用由locale控制的setlocale(),所以使用uppercaselowercase的做法很好地利用了API而没有太高级别。也就是说,如果您需要在运行英语语言环境的系统上处理法语名称,则需要更强大的实现。

答案 6 :(得分:1)

如果您正在寻找更通用的名称解决方案,您还应该看一下以下示例:

  • John Adams-Smith
  • Joanne d'Arc
  • Jean-Luc de'Breu
  • DonatienAlphonseFrançoisdeSade

名称的某些部分也不应以大写字母开头,例如:

  • Herbert von Locke
  • Sander van Dorn
  • Edwin van der Sad

所以,如果您正在考虑创建一个更通用的解决方案,请记住所有这些小事。

(这将是运行测试驱动开发的理想场所,具有您的方法/功能必须遵循的所有条件)

答案 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() {
  }

}