0

まず最初に、私が作成したこの単純なスクリプトには実際のアプリケーションがない可能性があることを述べたいと思いますが、私は学習中であり、ここ SO で同様のものを見つけることができなかったので、それを行いました。リストのようなイテラブル内の文字を「任意に」変更するにはどうすればよいか知りたかったのです。

確かtile()に、私は比較的すぐに習得した便利なツールですが、キックのために、代わりに最後の文字をフォーマット (大文字) したい場合はどうすればよいか考えなければなりませんでした。または3番目、中間のものなど。小文字はどうする?特定の文字を他の文字に置き換えますか?

私が言ったように、これは確かに完璧ではありませんが、私のような他の初心者に思考の糧を与えることができます. さらに、これを何百もの方法で変更して、あらゆる種類の異なるフォーマットを実現できると思います。

今やったことを改善するのを手伝ってくれませんか?それをもっと無駄のないものにしてみませんか?スタイル、方法、効率などのチェック...

ここに行きます:

words = ['house', 'flower', 'tree']  #string list

counter = 0                          #counter to iterate over the items in list
chars = 4                            #character position in string (0,1,2...)

for counter in range (0,len(words)): 
    while counter < len(words):
        z = list(words[counter])     # z is a temp list created to slice words
        if len(z) > chars:           # to compare char position and z length
            upper = [k.upper() for k in z[chars]] # string formatting EX: uppercase
            z[chars] = upper [0]     # replace formatted character with original
            words[counter] = ("".join(z)) # convert and replace temp list back into original word str list
            counter +=1
        else:
            break

print (words)

['housE', 'flowEr', 'tree']
4

4 に答える 4

2

私よりもはるかに優れたPythonistasがありますが、ここに1つの試みがあります。

[''.join(
      [a[x].upper() if x == chars else a[x]
          for x in xrange(0,len(a))]
    )
    for a in words]

また、プログラマーの4番目について話しているのですよね?他の誰もが5番目と呼んでいますね

于 2012-12-06T00:14:33.433 に答える
2

コードに関するいくつかのコメント:

for counter in range (0,len(words)):     
while counter < len(words):

whileループの下にループをインデントしない限り、これはコンパイルされませんfor。そして、そうすると、内側のループが外側のループのループ カウンターを完全に台無しにしてしまいます。そして最後に、Python で明示的なループ カウンターを保持することはほとんどありません。おそらくこれが必要です:

for counter, word in enumerate(words):

次:

z = list(words[counter])     # z is a temp list created to slice words

リストをスライスするのとまったく同じ方法で、すでに文字列をスライスできるので、これは不要です。

次:

    upper = [k.upper() for k in z[chars]] # string formatting EX: uppercase

まったく同じ名前の関数があり、同じ行で呼び出しているため、これは変数の不適切な名前です。

一方、あなたが物事を定義した方法z[chars]は、 のコピーである文字ですwords[4]。各文字自体が文字列であるため、Python では単一の文字を反復処理できます。<code>[k.upper() for k in z[chars]] は と同じものです[z[chars].upper()]

    z[chars] = upper [0]     # replace formatted character with original

つまり、最初の文字を取得するために 1 文字のリストだけが必要だったのに…そもそもなぜそれをリストにするのでしょうか? 最後の 2 行を に置き換えるだけz[chars] = z[chars].upper()です。

else:
    break

これは、長さ 4 より短い文字列をスキップするのではなく、長さ 4 より短い最初の文字列で停止します。その言い方はcontinue、ではありませんbreak。または、より良いのは、リストの最後から外れることです。を使わずに書くのが難しい場合もありますcontinueが、この場合は簡単です。すでにループの最後にあり、実際にelse:は他に何もない の中にあるので、両方の行を削除するだけです。

誤って 2 回呼び出した場合、1 回呼び出した場合と同じように見えるupperため、ループが間違っていると判断するのは困難です。upperを に変更するupperchr(ord(k)+1)、任意の文字が次の文字に置き換えられます。それからそれを試してください:

words = ['house', 'flower', 'tree', 'a', 'abcdefgh']

'flowgr'たとえば、の代わりにが得られることに気付くでしょう'flowfr'

内側のループを実行する回数をカウントアップする変数を追加することもできます。時間だけのはずlen(words)が、実はlen(words) * len(words)短い言葉がないか、len(words) * len(<up to the first short word>)ある場合です。コンピューターに余計な仕事をさせている.1000 語なら、1000 ループではなく 1000000 ループをしなければならない. O(N)になります。

すべてを一緒に入れて:

words = ['house', 'flower', 'tree', 'a', 'abcdefgh']  #string list
chars = 4                            #character position in string (0,1,2...)

for counter, word in enumerate(words): 
    if len(word) > chars:           # to compare char position and z length
        z = list(word)
        z[chars] = chr(ord(z[chars]+1) # replace character with next character
        words[counter] = "".join(z)    # convert and replace temp list back into original word str list

print (words)

これは元のコードと同じことを行い (「大文字」の代わりに「次の文字」を使用することを除いて)、バグがなく、コンピューターの作業がはるかに少なくなり、読みやすくなります。

于 2012-12-06T01:13:23.213 に答える
2

あなたが話している一般的なケースは、文字列とインデックスを指定すると、その文字列を返し、インデックス付きの文字が何らかの規則に従って変換されるメソッドだと思います。

def transform_string(strng, index, transform):
    lst = list(strng)
    if index < len(lst):
        lst[index] = transform(lst[index])
    return ''.join(lst)


words = ['house', 'flower', 'tree']
output = [transform_string(word, 4, str.upper) for word in words]

さらに抽象化するために、次のようにメソッドを返すファクトリを作成できます。

def transformation_factory(index, transform):
    def inner(word):
        lst = list(word)
        if index < len(lst):
            lst[index] = transform(lst[index])
    return inner
transform = transformation_factory(4, lambda x: x.upper())
output = map(transform, words)
于 2012-12-06T00:35:13.757 に答える
2

これは、両方の組み合わせのようなものです (両方に +1 :) )。メイン関数は、リスト、任意の関数、および操作対象の文字を受け入れます。

In [47]: def RandomAlter(l, func, char):
    return [''.join([func(w[x]) if x == char else w[x] for x in xrange(len(w))]) for w in l]
   ....:

In [48]: RandomAlter(words, str.upper, 4)
Out[48]: ['housE', 'flowEr', 'tree']

In [49]: RandomAlter([str.upper(w) for w in words], str.lower, 2)
Out[49]: ['HOuSE', 'FLoWER', 'TReE']

In [50]: RandomAlter(words, lambda x: '_', 4)
Out[50]: ['hous_', 'flow_r', 'tree']

この関数RandomAlterは、このように書き直すことができます。これにより、もう少し明確になる可能性があります (リスト内包表記と呼ばれる機能を利用して、必要なコード行を削減します)。

def RandomAlter(l, func, char):
    # For each word in our list
    main_list = []
    for w in l:
        # Create a container that is going to hold our new 'word'
        new_word = []
        # Iterate over a range that is equal to the number of chars in the word
        # xrange is a more memory efficient 'range' - same behavior
        for x in xrange(len(w)):
            # If the current position is the character we want to modify
            if x == char:
                # Apply the function to the character and append to our 'word'
                # This is a cool Python feature - you can pass around functions
                # just like any other variable
                new_word.append(func(w[x]))
            else:
                # Just append the normal letter
                new_word.append(w[x])

        # Now we append the 'word' to our main_list. However since the 'word' is
        # a list of letters, we need to 'join' them together to form a string
        main_list.append(''.join(new_word))

    # Now just return the main_list, which will be a list of altered words
    return main_list
于 2012-12-06T00:44:35.520 に答える