2012-04-16 9 views
1

20個の値ともう1つの配列を持つ配列(「origA」)を持っています(たとえば、「itemA」の値が1つだけです)。ランダムな値「itemA」への「ORIGA」の。しかし、私はすでに「itemA」に押し込まれる同じ値をプッシュすることはできません。私たちはこれを行うことができますどのようにランダムな値をある配列から別の配列に繰り返し渡します。

答えて

2
// Define how many random numbers are required. 
const REQUIRED:int = 10; 

// Loop until either the original array runs out of numbers, 
// or the destination array reaches the required length. 
while(origA.length > 0 && itemA.length < REQUIRED) 
{ 
    // Decide on a random index and pull the value from there. 
    var i:int = Math.random() * origA.length; 
    var r:Number = origA[i]; 

    // Add the value to the destination array if it does not exist yet. 
    if(itemA.indexOf(r) == -1) 
    { 
     itemA.push(r); 
    } 

    // Remove the value we looked at this iteration. 
    origA.splice(i, 1); 
} 
+0

彼は "無作為"と言っていましたが、あなたは知っています... – weltraumpirat

+0

私は明確ではないが、全部ではなく、繰り返しなしで10個のランダムな値が必要な場合は申し訳ありません。 – Sravan0313

+0

@ Marty Wallaceすべての値が "origA"で異なるため、この問題は発生しません。とにかく、私は繰り返しなしで言ったとき、私は、同じ値が再び押されるべきではない、 "origA"から "itemA"に1つのランダムな値がプッシュされることを意味しました。私が言いたいことが分かっている? – Sravan0313

3

あなたはコピーを作成することができますorigAを追加し、追加するアイテムをitemAに追加します。

非最適化されたバージョン:(ループ内lengthにノー呼び出し、indexOfspliceまたはpush

var origA:Array = [1, 2, 3, 4, 5, 6, 7]; 
var itemA:Array = [0]; 

var copyA:Array = origA.concat(); 
var N:int = 10; 
var n:int = Math.min(N, copyA.length); 

for (var i:int = 0; i < n; i++) { 
    // Get random value 
    var index:int = Math.floor(Math.random() * copyA.length); 
    var value:int = copyA[index]; 
    // Remove the selected value from copyA 
    copyA.splice(index, 1); 
    // Add the selected value to itemA 
    itemA.push(value); 
} 

trace(itemA); 
//0,1,7,2,6,4,3,5 

最適化されたバージョン:

var origA:Array = [1, 2, 3, 4, 5, 6, 7]; 
var itemA:Array = [0]; 

var copyA:Array = origA.concat(); 
var copyALength:int = copyA.length; 
var itemALength:int = itemA.length; 
var N:int = 10; 
var n:int = Math.min(N, copyALength); 
for (var i:int = 0; i < n; i++) { 
    // Get random value 
    var index:int = Math.floor(Math.random() * copyALength); 
    var value:int = copyA[index]; 
    // Remove the selected value from copyA 
    copyA[index] = copyA[--copyALength]; 
    // Add the selected value to itemA 
    itemA[itemALength++] = value; 
} 

trace(itemA); 
//0,2,5,7,4,1,3,6 

EDIT1:あなたの元の配列を持っている場合ほんの数アイテム、私の最初のバージョンまたは他の答えで他のソリューションを使用します。しかし、それが何千ものアイテムを持っているかもしれないなら、私はあなたが私の最適化されたバージョンを使用することをお勧めします。


編集:

  • 他のすべてのバージョン:2000ms
  • 最適化されたバージョン:12ms
  • ここで2
    1,000,000アイテムを含む配列から 1,000ランダムに選択された項目をコピーするのに要する時間であります
  • 元のアレイをクローン化しない最適化バージョン:1ms
+0

長さ10の配列や100未満の配列で作業しているとは思いますが、indexOf()がなくてもうまくいく解決法が本当に必要なわけではありませんが、はるかに大きい配列:) – Marty

+0

私は元の配列のコピーを主に(スプライス()を使用して)変更するのを避け、 'indexOf()'の使用を避けるために使用しました。2番目に最適化されたバージョンでは、高価なメソッドを呼び出さないようにしています: 'length'、' indexOf'、 'splice'、' push'です。 – sch

+0

私は 'indexOf()'の部分に同意しなければなりません - インデックスが見つかるまでインデックス0から反復します。これは大きな配列では非常にコストがかかることがあります。 – weltraumpirat

2

ここは本当に短いものです。あなたがMAXに到達するまで、ターゲットアレイにCONCAT、元の配列からランダムにアイテムを削除します。

const MAX:int = 10; 
var orig:Array = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]; 
var target:Array = []; 
var tmp:Array = []; 
var i : int = -1; 
var len : int = orig.length; 
while (++i < MAX && len > 0) { 
    var index:int = int(Math.random()*len); 
    tmp[i] = orig[index]; 
    orig[index] = orig[--len]; 
} 
target = target.concat(tmp); 

EDIT項目を除去するSCHの道@採用

。受け入れられるべき彼の答えです。私はちょうどwhileループのためにこれを保った。

関連する問題