2

重複の可能性:
リストではなくジェネレータ式を使用する sorted()

リストを常にインスタンス化する代わりにジェネレーターを使用すると、時間とメモリが節約されることは誰もが知っています。特に、内包表記を頻繁に使用する場合はそうです。

ただし、ここで質問があります。次のコードを検討してください。

output = SomeExpensiveCallEgDatabase()
results = [result[0] for result in output]
return sorted(results)

sorted を呼び出すと、ソートされた結果のリストが返されます。以下のように結果を宣言してから sorted を呼び出す方が良いですか、悪いですか?

results = (result[0] for result in output)

私の推測では、sorted() の呼び出しは、ジェネレーターをトラバースし、リスト自体をインスタンス化して、クイックソートまたはマージソートを実行します。したがって、ここでジェネレーターを使用しても利点はありません。この仮定は正しいですか?

4

3 に答える 3

3

最初にリスト全体をメモリに入れずにコレクションを並べ替える簡単な方法はないので、あなたの仮定は正しいと思います(少なくとも、デフォルトの並べ替えアルゴリズムであるTimSortを使用していない場合は間違いありません)。

これをチェックしてください: リストではなくジェネレータ式を使用してsorted()

新しいリストを作成するために、組み込みのsortedメソッドは以下を使用しますPySequence_List

PyObject * PySequence_List(PyObject * o)戻り値:新しい参照。任意のシーケンスoと同じ内容のリストオブジェクトを返します。返されるリストは新しいものであることが保証されています。

両方のアプローチの長所と短所:

メモリに関して:

返されるリストは、ソートされたバージョンに使用されるリストであるため、この場合、ジェネレーターバージョンを使用して、常に1つのリストのみが完全にメモリに格納されることを意味します。

これにより、ジェネレータバージョンのメモリ効率が向上します。

スピード:

ここでは、リスト全体を含むバージョンが優先されます。

ジェネレーターに基づいて新しいリストを作成するには、空のリストを作成し(または、せいぜい最初の要素を使用して)、後続の各要素をリストに追加する必要があります。

以前のリストに基づいて新しいリストを作成するには、リストのサイズが事前にわかっているため、一度に割り当てて各エントリを割り当てることができます(おそらく、ここで他の最適化が機能していますが、元に戻すことはできません)それまで)。

したがって、速度に関しては、リストが優先されます。

「何が最善か」に対する答えは、エンジニアリングのあらゆる分野で最も一般的な答えになります...それは異なります...。

于 2012-08-03T11:02:30.323 に答える
3

いいえ、まだ新しいリストを作成していますsorted()

output = SomeExpensiveCallEgDatabase()
results = [result[0] for result in output]
results.sort()
return results

ジェネレーターのバージョンに近いでしょう。

ジェネレーターバージョンを使用する方が良いと思います。Pythonの将来のバージョンでは、これを利用してより効率的に機能する可能性があるためです。無料でスピードを上げるのはいつでもいいことです。

于 2012-08-03T11:03:27.140 に答える
0

はい、あなたは正しいです(ただし、おじさんのtimmy <wink-ly y'rs>の後、並べ替えルーチンはまだtim-sortと呼ばれていると思います)

于 2012-08-03T11:02:10.330 に答える