2017-07-07 3 views
12

JSのこの2次元配列に問題があります。 a[1][0]を変更すると、a[0][0]が変更されます。私はそれを初期化する方法に何か間違っていますか?はいの場合は、どうすれば適切に初期化できますか?fillを使用して作成されたこの2次元配列の他のセルに変更が加えられたのはなぜですか?

>var a = Array(100).fill(Array(100).fill(false)); 
>a[0][0] 
>false 
>a[1][0] 
>false 
>a[1][0] = true 
>true 
>a[1][0] 
>true 
>a[0][0] 
>true 
+3

あなたは 'a.fillは()'引数の単一のインスタンスを作成し、(オブジェクトのような挙動を)それをコピーしないことを、覚えておいてください。したがって、 'a'のすべての要素は同じ正確なオブジェクトです。 –

+0

この質問は、各言語の文字通り数十回現れます。 –

答えて

1

重複質問のようなこれらのルックスが、私はいつもちょうどクレジットこの

var x = new Array(10); 
for (var i = 0; i < 10; i++) { 
    x[i] = new Array(10).fill(false); 
} 
x[5][5] = true 

のようなものを使用しました:How can I create a two dimensional array in JavaScript?

17
var a = Array(100).fill(Array(100).fill(false)); 

aは、アレイ、参照の各要素が含まれていますアレイに。すべての偽の値を含む配列で外側の配列を塗りつぶしています。内部配列は1回だけ作成され、同じ配列への参照が外部配列の各要素に渡されるため、ある要素に対して操作を実行すると他の要素にも反映されます。

これは実際にここに

var a1 = Array(100).fill(false); 
var a = Array(100).fill(a1); 

aと同等であるが、全て同じ配列a1への参照を有する100個の要素を取得します。したがって、aの1つの要素を変更した場合、すべての要素は同じ配列への参照であるため変更されます。

外部配列の各要素を新しい配列で埋める必要があります。あなたの問題は、あなたが最初の配列のどの位置に第二Array(100).fill(false)を使用していることである

var a = []; 
for(var i=0; i<100; i++) 
    a.push(Array(100).fill(false)); 
3

:あなたはこのような何かを行うことができます。 「2番目の」次元で1つの値を変更すると、配列のすべての単一の位置で変更されるのはなぜですか。これを避けるには、初期の各位置に対して新しい配列を作成する必要があります。

var x = Array(100).fill().map(x => Array(100).fill(false)); 
+0

動作しません。 'map()'関数は、疎配列の未定義のプロパティに対しては動作しません。 –

+0

最初の配列を忘れてしまった – nicowernli

2

大きな配列の各インデックスに同じ配列オブジェクトを追加しています。

あなたが実際に何をしている

Array(x).fill(Array(y).fill(false)); 

を行うときにそうである:

Array(x).fill(Y); // i.e. X.fill(Y) 

あなたはYを変更するたびに今、あなたはX.

の各インデックスに同じ値を取得します

データ自体がオブジェクトの場合は、ループを使用してデータを入力する必要があります(Arrayはオブジェクトであることを忘れないでください)。

7

あなたの全体の配列は、同じ(二次元)配列オブジェクトへの参照で充填されます。初期配列の値が明示的に何か(に設定する必要があること

const a = Array(100).fill(false).map(x => Array(100).fill(false)); 
 

 
a[0][0] = true; 
 

 
console.log(a[0][0]); 
 
console.log(a[0][1]); 
 
console.log(a[1][1]);

注:異なるオブジェクトでそれを埋めるために

、あなたはこのような何かをする必要があると思います私の例ではfalseですが、undefinedでも構いません)コンストラクタによって作成された配列は疎であり、map()関数は実際に存在するプロパティに対してのみ動作するためです。それを回避するために

、あなたがArray.from()を使用することができる:

const a = Array.from(Array(100), x => Array(100).fill(false)); 
 

 
a[0][0] = true; 
 

 
console.log(a[0][0]); 
 
console.log(a[0][1]); 
 
console.log(a[1][1]);

1

配列が参照型であるため、JSにおけるN次元配列を作成することはそれほど簡単ではありません。最初にクローンツールを作成する必要があります。

Array.prototype.clone = function(){ 
 
    return this.map(e => Array.isArray(e) ? e.clone() : e); 
 
}; 
 

 
function arrayND(...n){ 
 
    return n.reduceRight((p,c) => c = (new Array(c)).fill().map(e => Array.isArray(p) ? p.clone() : p)); 
 
} 
 

 
var arr = arrayND(2,3,4,"x") 
 
console.log(JSON.stringify(arr));

arrayNDは、各次元のサイズを指定する整数の引数の不定の数を取り、最後の引数は、充填値です。

0

mdnで説明したfill関数は、すべての配列インデックスに同じ値をコピーします。以下のユーティリティを使用して配列のクローンを作成することができます。しかし、私はスライス演算子を使用しているので、これは配列のクローニングに限られています。

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/fill

if (!Array.prototype.clonefill) { 
    Object.defineProperty(Array.prototype, 'clonefill', { 
    value: function(value) { 

     // Steps 1-2. 
     if (this == null) { 
     throw new TypeError('this is null or not defined'); 
     } 

     var O = Object(this); 

     // Steps 3-5. 
     var len = O.length >>> 0; 

     // Steps 6-7. 
     var start = arguments[1]; 
     var relativeStart = start >> 0; 

     // Step 8. 
     var k = relativeStart < 0 ? 
     Math.max(len + relativeStart, 0) : 
     Math.min(relativeStart, len); 

     // Steps 9-10. 
     var end = arguments[2]; 
     var relativeEnd = end === undefined ? 
     len : end >> 0; 

     // Step 11. 
     var final = relativeEnd < 0 ? 
     Math.max(len + relativeEnd, 0) : 
     Math.min(relativeEnd, len); 

     // Step 12. 
     while (k < final) { 
     O[k] = value.slice(0); 
     k++; 
     } 

     // Step 13. 
     return O; 
    } 
    }); 
} 
Array(100).clonefill(Array(100)) 
a[0][0] = true 
a[1][0] 
false 
関連する問題