3

この例では「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() というライブラリ関数があることは知っているが、「本格的なプログラミング」をしたい。

これを修正するにはどうすればよいですか?

4

9 に答える 9

11

あなたが達成しようとしていることは次のとおりだと思います:

from string import capwords
capwords(name)

どちらが得られますか:

'Markus Johansson'

編集: OK、開いたドアを取り壊したいようですね。これが低レベルの実装です。

''.join([char.upper() if prev==' ' else char for char,prev in zip(name,' '+name)])
于 2009-03-04T09:31:19.833 に答える
9
>>> "markus johansson".title()
'Markus Johansson'

組み込みの文字列メソッドが最適です。

編集: 車輪を再発明したいのですね。特に理由はありますか?次のような複雑な方法をいくつでも選択できます。

' '.join(j[0].upper()+j[1:] for j in "markus johansson".split())

標準ライブラリはまだ道のりです。

于 2009-03-04T10:55:15.607 に答える
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;
}

str.title()純粋な Python で

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
于 2009-03-04T12:08:36.290 に答える
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)
于 2009-03-04T09:31:16.323 に答える
2

名前のより一般的な解決策を検討している場合は、次の例も確認する必要があります。

  • ジョン・アダムズ・スミス
  • ジョアン・ダルク
  • ジャン=リュック・ド・ブルー
  • ドナティエン・アルフォンス・フランソワ・ド・サド

また、名前の一部は、次のように大文字で始めるべきではありません。

  • ヘルベルト・フォン・ロック
  • サンダー・ヴァン・ドーン
  • エドウィン・ヴァン・デル・サド

したがって、より一般的なソリューションの作成を検討している場合は、これらすべてのささいなことを念頭に置いてください。

(これは、メソッド/関数が従わなければならないすべての条件を備えた、テスト駆動開発を実行するのに最適な場所です) .

于 2009-03-04T13:35:03.257 に答える
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()います... 参考までにupper()locale制御されたも使用setlocale()するため、使用の実践とuppercaselowercaseレベルになりすぎない API の適切な使用です。とはいえ、たとえば、英語のロケールを実行しているシステムでフランス語の名前を処理する必要がある場合は、より堅牢な実装が必要になります。

于 2009-03-04T11:42:23.577 に答える
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 で始まる名前に対してのみ機能します。

于 2009-03-04T09:37:03.970 に答える
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 の孫」を意味するように変更します。

于 2009-03-04T11:07:10.650 に答える