0

記号や空白を無視してテキストファイルから文字を読み取り、各文字の数を最も一般的なものから最も一般的でないものの順に出力するプログラムを作成したいと思います。

さらに、私は最初のプログラミングクラスでこれに取り組んでいるため、カウンターを使用することは許可されていません。

私はこれまでにこれを持っています:

name= raw_input("Enter file name:")
fl= open(name, 'r+').read()
lw= fl.lower()
ws= lw.replace(' ','')
sm= ws.translate(None, ",-!.;?:")
occ= {}
alpha= list ('abcdefghijklmnopqrstuvwxyz')
for x in alpha:
    occ[x]= sm.count(x)
for x in occ:
    print x, occ[x]

テキストファイルが次のようなものであると偽ってください:「私はこれに非常に混乱していますか?」

次に、プログラムはプログラミングを実行し、これを実行します:「iamhighlyconfusedbythis」

しかし、今のところ、次のようなものしか表示されません。

1   a
1   b
1   c
1   d
1   e
1   f
1   g
3   h
3   i
0   j
0   k
1   l
1   m
1   n
1   o
0   p
0   q
0   r
2   s
1   t
1   u
0   v
0   w
0   x
2   y
0   z

しかし、私は結果を次のようにしたいと思います。

3   h
3   i
2   s
2   y
1   e
1   f
1   g
1   a
1   b
1   l
1   m
1   n
1   o
1   c
1   t
1   u
1   d
0   j
0   k
0   p
0   q
0   r
0   v
0   w
0   x
0   z

私は以下のアイデアを使用しました:

spyshyguy

暗号文の文字頻度の決定

SimplyZ

Pythonでの文字の頻度

4

5 に答える 5

5

更新された問題の解決策

>>> from collections import defaultdict
>>> import string
>>> text = 'I am highly confused by this?'.lower().translate(None,string.punctuation+' ')
>>> c = defaultdict(int)
>>> c.update({letter:0 for letter in string.lowercase[:26]}) #Initialize each letter of alphabet to 0
>>> for letter in text:
        c[letter] += 1


>>> for letter,freq in sorted(c.iteritems(),key=lambda (l,f): (-f,l)): #Sort by frequency in descending order by making frequency negative then by letter in ascending order
        print freq, letter


3 h
3 i
2 s
2 y
1 a
1 b
1 c
1 d
1 e
1 f
1 g
1 l
1 m
1 n
1 o
1 t
1 u
0 j
0 k
0 p
0 q
0 r
0 v
0 w
0 x
0 z

元の問題の解決策:次 を使用できますcollections.Counter

>>> from collections import Counter
>>> import string
>>> text = 'I am highly confused by this?'.translate(None,string.punctuation+' ')
>>> print ' '.join('%d %s'%(freq,letter) for letter,freq in Counter(x).most_common())
3 h 2 i 2 s 2 y 1 a 1 c 1 b 1 e 1 d 1 g 1 f 1 I 1 m 1 l 1 o 1 n 1 u 1 t
于 2012-04-14T03:28:15.570 に答える
3

あなたはこれを行うことができます、

from operator import itemgetter
for k,v in sorted(occ.items(), key=itemgetter(1), reverse=True):
    print k, v

しかし、文字を数えるためのより良い方法があります。collections.Counter

于 2012-04-14T03:24:41.437 に答える
1

これは、を使用した単純なPythonバージョンdefaultdict()です。これはクラス用だと言ったので、これはあなたが要求した最終的な解決策ではありません。

from collections import defaultdict
from operator import itemgetter

d = defaultdict(int)

name = raw_input("Enter file name: ")

with open(name, "r") as f:
    for line in f:
        for ch in line:
            if ch.isalpha():
                d[ch] += 1

lst = d.items()

# sort twice: once for alphabetical order, then for frequency (descending).
# Because the Python sort is "stable", we will end up with descending
# frequency, but alphabetical order for any frequency values that are equal.
lst.sort(key=itemgetter(0))
lst.sort(key=itemgetter(1), reverse=True)

for key, value in lst:
    print value, key,

ここのように、開いているファイルでforループを実行するとfor line in f、Pythonは入力ファイルから一度に1行を取得します。次に、入力行で一度に1文字ずつループします。次に、それが文字であるかどうかを確認し、そうである場合は、文字の頻度カウントをインクリメントします。

このコードにはバグがあります。すべての文字の頻度をすべて小文字であるかのようにカウントする必要がありますが、このコードでは、1つのカウントが大文字で、別のカウントが小文字で保持されます。カウントが小文字のみになるようにこれを変更する方法を理解できると確信しています。

カウントが完了したら、.items()メソッド関数を使用して(key, value)タプルのリストを取得します。例:('h', 3)は、辞書のキー文字hとその値、カウント3を持つタプルです。

次に、並べ替えます。Pythonが実行できる巧妙なトリックを紹介します。並べ替えは「安定した」並べ替えであるため、複数の並べ替えを行う場合、Pythonは必要がない限り以前の並べ替えの結果を妨げません。つまり、最初にアルファベット順に並べ替え、次に頻度カウントで並べ替えると、頻度カウントが等しいすべての場合に、その頻度内でアルファベット順になります。したがって、、、aおよびbcすべて同じ頻度であるため(それぞれが一度表示される)、出力の一部は次のようになります。1 a 1 b 1 c

今、私は少しトリッキーですが、これは学ぶのに良いです。sort関数はkey、sortを制御するという引数を取ることができます。 keyソートに使用する値を返す関数である必要があります。タプルのリストがあるので、タプルの一部を取得して返すことができるキー関数が必要です。2つの関数を書くことができます:

def get_key(kv_tuple):
    return kv_tuple[0]
def get_value(kv_tuple):
    return kv_tuple[1]

しかし、Pythonには、operator.itemgetter()使用できる関数、があります。タプルのどの位置を取得したいかを指示するだけで、タプルの一部を取得する重要な機能になります。

最初に頻度を最大値でソートする必要があるreverse=Trueため、メソッドの引数も設定します.sort()

最後に、キー、値のタプルのリストをループして印刷します。

このコードには別の問題があります。出力例は、すべての文字をリストに含めたいことを示しています。文字が入力に含まれていなかった場合は、カウントが0になります。これはそこにあったものだけを数えます。

したがって、このコードを書き直すことをお勧めします。を使用する代わりにdefaultdict、通常のを使用してみてください。ただし、各文字をカウント0のにdict設定するループがあります。azdict

dictまた、カウントしたい文字を含む通常の文字を取得したら、カウントするかどうかを決定するコードを変更することをお勧めします。現在、.isalpha()メソッド関数を使用して、文字をカウントするかどうかを決定しています。in代わりに、文字が辞書であるかどうかを確認できます。次に、このコードを使用して、句読点や数字、または任意の種類の文字をカウントできます。

于 2012-04-14T03:55:25.073 に答える
1

カウンターを使用できないため、次のようにします。

from string import ascii_lowercase

with open(name, 'r') as f:
    raw_text = f.read().lower()

letterCounts = [raw_text.count(letter) for letter in ascii_lowercase]

frequencies = reversed(sorted(zip(ascii_lowercase, letterCounts), lambda x: x[1]))

for i in frequencies:
    print "%s: %d" % i
于 2012-04-14T03:48:35.647 に答える