1

誰でもこのコード ブロックを最適化できますか? 動作していますが、動作が非常に遅いです。

maxsat = 0
possiblevotes = []
for i in range(1,int(numcats)+1):
    for j in range(1,int(numdogs)+1):
        possiblevotes.append('C' + str(i) + ' ' + 'D' + str(j))
        possiblevotes.append('D' + str(j) + ' ' + 'C' + str(i))
for m in possiblevotes:
    count = 0
    for n in votes:
        if m == n:
            count += 1
        elif m.split()[0] == n.split()[0]:
            count += 1
    if count > maxsat:
        maxsat = count
4

4 に答える 4

1

考えられるすべての票を生成する必要はありません。possiblevotes既存の投票が可能かどうかを簡単に計算できるため、リストを生成しなくても実際の投票をテストできます。

また、実際には「滞在」票のみをカウントします。一致する 'stay go' 投票を探すことは問題ではありません。true である 'stay go' 投票はすべてtruem == nm.split()[0] == n.split()[0]あるためです。したがって、最初のカウントを削除して、2 番目のカウントのみを確認することもできます。

これで、投票の最大数を見つけることができましたstay。a を使用すると、collections.Counter()物事を簡単に数えることができます。

import collections

vote_counts = collections.Counter(v.split()[0] for v in votes)

maxsat = vote_counts.most_common(1)[0][1]  # retrieve the most popular count

これは、コードが計算したのと同じ数を計算しますが、投票を 1 回ループするだけで済み、「滞在」投票のみをカウントする必要があります。

numcats * numdogsこれを、最初にループ時間を、次にループ時間をループするループと対比してくださいnumcats * numdogs * 2 * len(votes)3 * numcats * numdogs それはより大きな要因です。

最初に投票を検証する必要がある場合は、次を使用できます。

from itertools import ifilter

numcats = int(numcats)
numdogs = int(numdogs)

def validvote(vote):
    stay, go = vote.split()
    cat, dog = sorted((stay, go))
    if (cat[0], dog[0]) != ('C', 'D'):
        return False
    if not (1 >= int(cat[1:]) >= numcats):
        return False
    if not (1 >= int(dog[1:]) >= numdogs):
        return False
    return True

vote_counts = collections.Counter(v.split()[0] for v in ifilter(validvote, votes))

go投票の使用を開始することもできます。

stay_votes = collections.Counter()
go_votes = collections.Counter()

for vote in ifilter(validvote, votes):
    stay, go = vote.split()
    stay_votes[stay] += 1
    go_votes[go] += 1

これで、滞在投票の集計からゴー投票を単純に差し引くことができます(集計が 0 になった場合は削除されます)。

total_votes = stay_votes - go_votes

# Display top 10
for creature, tally in total_votes.most_common(10):
    print('{}: {:>#5d}'.format(creature, tally))

もちろん、一度に計算を行うこともできます。

total_votes = collections.Counter()

for vote in ifilter(validvote, votes):
    stay, go = vote.split()
    total_votes[stay] += 1
    total_votes[go] -= 1

しかし、投票の集計を別々にしておくことは、後の分析にとって興味深いかもしれません。

于 2013-02-26T16:53:10.520 に答える
0

リストの代わりに辞書を使用します。

possiblevotes = {}
for i in range(1,int(numcats)+1):
    for j in range(1,int(numdogs)+1):
        possiblevotes['C' + str(i) + ' ' + 'D' + str(j)] = 0
        possiblevotes['D' + str(j) + ' ' + 'C' + str(i)] = 0
for n in votes:
    possiblevotes[n] += 1
....
于 2013-02-26T16:35:26.640 に答える
0

ループが入れ子になっているため、コードに時間がかかります。1000 匹の猫、1000 匹の犬、1000 票の場合、最初のループ セットは 1000x1000 回実行されます。2 番目のセットは 1000x1000x1000 回実行されます。ネストされたループを削除できれば、コードはより高速に実行されます。

「C1 D3」が「D3 C1」と同じである票を集計しているようです。Collections モジュールの Counter クラスを使用して、面倒な作業を行うことをお勧めします。これが私の解決策です:

import collections

if __name__ == '__main__':
    votes = ['C1 D3', 'D1 C5', 'D3 C1', 'd1 c1', 'c1 d3'] # Example votes

    # Normalize the votes: 'D3 C1' becomes 'C1 D3',
    # 'c1 d3' becomes 'C1 D3'
    normalized_votes = [''.join(sorted(v.upper().split())) for v in votes]

    # Count the votes
    counter = collections.Counter(normalized_votes)

    # Top 10
    print '--- TOP 10 ---'
    for vote, count in counter.most_common(10):
        print count, vote

    # Or print all
    print '--- ALL ---'
    for vote, count in counter.iteritems():
        print count, vote

討論

  • このソリューションでは 4 つのループを使用します。1つ目はnormalized_votesを導出するためのもので、2 つ目はカウンタ変数を作成するためのものです。最後の 2 つのループは、結果の出力を処理します。これらのループはネストされていません。クラスの実装にはネストされたループが含まれている可能性があると主張する人もいるかもしれませCounterんが、私はこのクラスが可能な限り効率的に実装されていると信じています。

  • 重要なステップの 1 つは、投票を正規化することです。これにより、集計が大幅に簡素化されます。ここでは 1 行で説明しましたが、理解を助けるためにいくつかのステップに分割できます。

    1. 最初のステップは、すべての票を大文字に変換することです。「d3 c1」は「D3 C1」になります。
    2. 次に、split()関数を使用してそれらをリストに分割します。'D3 C1' は ['D3', 'C1'] になります。
    3. 3 番目のステップは、各アイテムをソートすることです。['D3', 'C1'] は ['C1', 'D3'] になります。
    4. 最後のステップでそれらを元に戻します: ['C1', 'D3'] は 'C1 D3' になります
于 2013-02-26T17:12:23.353 に答える
0
import re

vote_pattern = re.compile('^(C|D)\d+\s')

votes = ['123', 'A1123', 'cC32', 'C', 'D0', 'C11']
maxsat = sum(0 if vote_pattern.match(vote) is None else 1 for vote in votes)

もちろん、このひどい合計をフィルターのようなものに変更できます。

于 2013-03-03T18:50:15.997 に答える