2

Enumerator妥当な時間内にインスタンスの無限シーケンスのスライスを取得するのに問題があります。私は最初dropにチェーンを試みましたが、無限を返そうとしたため、take永遠にハングしました。次に、これらのメソッドの順序を切り替えましたが、1000万番目のサンプルの後で100個の値を取得するには、まだ約10分待つ必要があります。dropArray

print exbioseq.drop(10**7).take(100)

スライスを速くするために何かできることはありますか?

4

1 に答える 1

2

は非常に一般的なEnumeratorインターフェイスであり、通過する「コレクション」について非常に単純な仮定のみを行います。特に、実際には 2 つの操作しかサポートしていません。現在の要素を取得し、次の要素に反復します。

これら 2 つの操作を考えると、1000 万番目の要素を取得したい場合、できることは 1 つだけです。1000 万回繰り返すことです。これには時間がかかります。

を「スライス」することはありませんEnumeratorEnumerator列挙します。それでおしまい。

さて、あなたが発見したように、別の問題があります: Ruby のコレクション操作は型を保存しません。どのタイプのコレクションを呼び出してmapも、常に同じタイプ、つまり完全に実現された具体的な strict を返しselectます。これは、ほとんどの言語でほとんどのコレクション フレームワークが機能する方法です。たとえば、.NET では、すべてのコレクション操作が returnです。これは、これらのメソッドのほとんどがmixin に共通の実装を 1 つしか持たないためです。takeArrayIEnumerableEnumerable

Smalltalk は例外ですが、別の問題があります。コレクション操作は、すべてのコレクション タイプで重複します。collect:すべてのコレクション タイプには、などの実質的なコピー アンド ペーストの実装がほとんどない独自のものがあります。このコードの重複は維持が難しく、独自のコレクションをフレームワークselect:に統合したい人にとっては大きな負担となります。Ruby では簡単です。implement とmixinを実行すれば完了です。eachEnumerable

注: Ruby 1.9 の時点で、実際にはその重複がいくつかあります。 は、実際には ではなく を返すHash独自のバージョンを実装しています。そのため、コードの重複だけでなく、インターフェイスの非対称性も生じています。selectHashArrayselectArrayHash

Scala 2.8 のコレクション フレームワークは、コードの重複なしに型を保持するコレクション操作を提供する方法を誰かが見つけた初めての例です。しかし、Ruby のコレクション フレームワークは Scala 2.8 より 15 年前に設計されたため、その知識を利用することはできません。

Ruby 2.0 にはEnumerator、すべてのコレクション操作が別の lazy を返す lazy がありEnumeratorます。しかし、それはここでは役に立ちません: 唯一の違いは、怠惰な人が実際に値Enumeratorを取得するまで 1,000 万回の反復を遅らせることです。print他に方法がないため、1,000 万回の反復を実行する必要があります。

スライスが必要な場合は、 などのスライス可能なデータ構造が必要ですArray

于 2013-02-20T11:39:53.653 に答える