8

一意の整数キーに基づくデータセットのサイズが未定です。

NSMutableArrayすべてのキーが整数ベースであるため、高速ルックアップにを使用したいと思います。

これをやりたいです。

NSMutableArray* data = [NSMutableArray array]; // just create with 0 size

その後、人々は整数インデックス(すべて一意)を使用してデータを私に投げ始めるので、私はこのようなことをしたいだけです...

if ([data count] < index)
    [data resize:index];  // ? how do you resize

配列のサイズを変更して、次のことができるようにします...

[data insertObject:obj atIndex:index];

最後のサイズと新しいサイズの間のすべてのスロットはゼロであり、最終的には後で埋められます。

だから私の質問は、既存のサイズを変更するにはどうすればよいNSMutableArrayですか?

ありがとう、ローマン

4

4 に答える 4

32

NSPointerArray を使用します。

http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSPointerArray_Class/Introduction/Introduction.html

NSPointerArray は NSArray をモデルにした変更可能なコレクションですが、NULL 値を保持することもでき、挿入または抽出できます (オブジェクトのカウントに寄与します)。さらに、従来の配列とは異なり、配列のカウントを直接設定できます。ガベージ コレクション環境でゼロ化の弱いメモリ構成を指定すると、要素が収集されると、その要素は NULL 値に置き換えられます。

辞書のようなソリューションを使用する場合は、NSMapTable を使用してください。整数キーを許可します。推奨される NSMutableDictionary ベースのソリューションには、整数キーのボックス化とボックス化解除のすべてに関連する膨大な量のオーバーヘッドがあります。

于 2009-08-31T15:02:25.457 に答える
19

あなたのニーズは。でよりよく満たされるように思えますNSMutableDictionaryint次のように、 sをNSNumberオブジェクトにラップする必要があります。

-(void)addItem:(int)key value:(id)obj
{
    [data setObject:obj forKey:[NSNumber numberWithInt:key]];
}

-(id)getItem:(int)key
{
    return [data objectForKey:[NSNumber numberWithInt:key]];
}

NSMutableArray中間のスロットにnilオブジェクトを含めることはできないため、のサイズを拡大するのは簡単ではありませんでした。ただし、[NSNull null]「フィラー」として使用して、スパース配列の外観を作成することはできます。

于 2009-08-30T21:39:44.220 に答える
1

ジェイソンの答えのように、 NSMutableDictionary が最良のアプローチのようです。インデックス値を NSNumbers との間で変換するオーバーヘッドが追加されますが、これは古典的な空間/時間のトレードオフです。

私の実装では、まばらな配列のトラバースをより簡単にするために NSIndexSet も含めました。

https://github.com/LavaSlider/DSSparseArrayを参照してください

于 2014-05-26T17:38:33.627 に答える
-3

これに関するbbumの答えには同意できません。ANSPointerArrayはスパース配列ではなく配列であり、この 2 つには重要な違いがあります。

bbums ソリューションを使用しないことを強くお勧めします。

のドキュメントは、こちらからNSPointerArray入手できます。

NSArrayCocoa には、クラス で定義された配列オブジェクトが既にあります。NSPointerArrayから継承しNSObjectているため、 の直接のサブクラスではありませんNSArray。ただし、NSPointerArrayドキュメントではクラスを次のように定義しています。

NSPointerArray is a mutable collection modeled after NSArray but it can also hold NULL values

ドキュメントからのこの定義は、これがNSArray.

定義-

「一般的な」配列とは、アイテムのコレクションであり、それぞれに固有のインデックス番号が関連付けられています。

修飾なしの配列は次のとおりです: 項目のインデックスが次のプロパティを持つ「一般的な」配列: 配列内の項目のインデックスは で始まり、0順次増加します。配列内のすべての項目には、配列内の項目数よりも小さいインデックス番号が含まれています。配列への項目の追加は、配列内の最後の項目のインデックス + 1 である必要があります。または、2 つの既存の項目インデックス番号の間に項目を挿入して、後続のすべての項目のインデックス番号を 1 ずつ増やすことができます。既存のインデックス番号の項目は別の項目に置き換えることができ、この操作は既存の操作のインデックス番号を変更しません。したがって、挿入と置換は 2 つの異なる操作です。

スパース配列は次のとおりです。最初の項目のインデックス番号が任意の番号で開始でき、配列に追加される後続の項目のインデックス番号が、配列内の他の項目との関係や制限を持たない「一般的な」配列です。スパース配列に項目を挿入しても、配列内の他の項目のインデックス番号には影響しません。通常、アイテムの挿入とアイテムの置換は、ほとんどの実装で同義です。疎配列内の項目数のカウントは、疎配列内の項目のインデックス番号とは関係ありません。

これらの定義は、テスト可能な「ブラック ボックス」配列の動作について特定の予測を行います。簡単にするために、次の関係に注目します。

配列では、配列内のすべてのアイテムのインデックス番号は、配列内のアイテム数のカウントよりも小さくなります。これはスパース配列には当てはまりますが、必須ではありません。

bbum へのコメントで、私は次のように述べました。

aNSPointerArrayはスパース配列ではなく、スパース配列のようにも動作しません。未使用のすべてのインデックスをNULLポインターで埋める必要があります。[pointerArray insertPointer:@"test" atIndex:17];新しくインスタンス化されたからの出力NSPointerArray:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSConcretePointerArray insertPointer:atIndex:]: attempt to insert pointer at index 17 beyond bounds 0'

証明することなく、NSPointerArray上記の動作はまばらな配列の定義そのものに違反していると述べられています。エラー メッセージのこの部分は明らかにしています: attempt to insert pointer at index 17 beyond bounds 0'、特に最初の新しい項目を index に追加する必要があることに関する部分0です。

bbum 次にコメントします。

それは正しくありません。容量を十分なサイズに設定するための -setCount: の呼び出しに失敗しました。

スパース配列のアイテム数の「カウントを設定」することは無意味です。が疎配列の場合NSPointerArray、インデックス 17 に最初のアイテムを追加した後、 内のアイテム数のカウントは 1 になると予想されますNSPointerArray。ただし、bbums のアドバイスに従って、NSPointerArray最初のアイテムを追加した後の のアイテム数は であり18、 ではありません1

QED- aNSPointerArrayが実際には配列であることが示され、この議論の目的のために、 a NSArray.

さらに、bbum は次の追加コメントを作成します。

NSPointerArray は確実に穴をサポートします。

これは間違いです。配列には、その何かが「何もない」場合でも、含まれるすべての項目に何かが含まれている必要があります。これはスパース配列には当てはまりません。これは、この議論における「穴」のまさに定義です。Aは、用語のスパース配列の意味にNSPointerArray含まれていません。holes

それは、クラスを書く上での全体的なポイントの 1 つでした。最初にカウントを設定する必要があります。

スパース配列の「カウントを設定する」ことは、おそらく無意味です。

内部実装がスパース配列であるかハッシュであるか、またはその他であるかは、実装の詳細です。

これは本当です。ただし、のドキュメントでNSPointerArrayは、アイテムの配列を実装または管理する方法については言及されていません。NSPointerArrayさらに、 「が NULL ポインタの配列を効率的に管理する」とはどこにも述べていません。

QED-bbum は、スパース配列を介してポインターを内部的に効率的に処理する、文書化されていない動作に依存しています。文書化されていない動作であるため、この動作はいつでも変更される可能性があり、. 格納されている最大のインデックス番号が十分に大きい場合 (~ 2^26) 、この動作の変更は壊滅的です。NSPointerArrayNULLNSPointerArray

そして、実際には、1 つの大きなメモリの塊として実装されているわけではありません...

繰り返しますが、これは文書化されていない非公開実装の詳細です。このタイプの動作に依存することは、プログラミングの実践としては非常に不適切です。

于 2009-09-03T23:56:34.863 に答える