web-dev-qa-db-ja.com

Javascript 2D配列indexOf

私はこのような2D配列を持っています:

_var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];
_

各インデックスには、いくつかの要素の座標を含む内部配列が格納されます。

Array.indexOf() を使用して、新しく生成された座標セットが既にarrに含まれているかどうかを確認するにはどうすればよいですか?座標だけが重複していない場合、arrにプッシュしたいです。

うまくいかなかった私の試みは次のとおりです。

_if (arr.indexOf([x, y]) == -1) {
    arr.Push([x, y]);
}
_

indexOf()は2D配列では機能しないようです...

22
phoeberesnik

IndexOfを使用して複雑な配列を実行することはできません(各座標をすべて文字列にするためにシリアル化しない限り)、forループ(またはwhile)を使用して、配列の形式を知っていると仮定してその配列内の座標を検索する必要があります(この場合、2dです。

var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];
var coor1 = [0, 9];
var coor2 = [1, 2];

function isItemInArray(array, item) {
    for (var i = 0; i < array.length; i++) {
        // This if statement depends on the format of your array
        if (array[i][0] == item[0] && array[i][1] == item[1]) {
            return true;   // Found it
        }
    }
    return false;   // Not found
}

// Test coor1
console.log("Is it in there? [0, 9]", isItemInArray(arr, coor1));   // True

// Test coor2
console.log("Is it in there? [1, 2]", isItemInArray(arr, coor2));   // False

// Then
if (!isItemInArray(arr, [x, y])) {
   arr.Push([x, y]);
}

この実装は、すべての値をループして取得します。パフォーマンスに関心がある場合は、最初のインデックスで元の配列をソートし、最初のインデックスでバイナリ検索を使用するなど、より複雑なことを行うことができます。

別の方法は、オブジェクト(ハッシュテーブルなど)の配列内の各項目の最初の座標をバケット化し、それらのバケットのそれぞれで2番目の値をバケット化して検索時間を短縮することです。詳細はこちら http://en.wikipedia.org/wiki/Bucket_sort

それ以外の場合、これはおそらくあなたが必要とするものに対して十分です。

18
user654628

Working js fiddle

for(var k = 0; k < arr.length; k++){
    if(arr[k][0] == x && arr[k][1] == y){
        found = true;
    }
}

単純なインデックスよりもはるかにハッキーな方法ですが、動作します

6
joegandy

完全な答えではなく、役に立つかもしれないサイドノートだけです。

Lodashを使用

このメソッドは、2次元配列内の値の位置を取得します

let a = [ [ 'bird' ], [ 'cat' ], [ 'dog' ], [ 'cow' ], [ 'bird' ] ];
let b = _.findIndex(a, function(el) { return el[0] == 'cow'; });
console.log(b);//answer is 3

前述のように、配列内を移動するにはネストされたループが必要です。

2
Mendo

これは2次元配列であるため、ネストされたforループが必要です。

var newArr = [1, 2],
    counter;


for ( var i = 0; i < arr.length; i++ ) {

    for ( var x = 0; x = arr[i].length; x++ ) {

        if ( arr[i][x] === newArr[x] {

             counter++ 
        }

        if (counter === 2) {
            alert('new coord!')
        }
    }
    //reset counter
    counter = 0;
}
1
bencripps

IndexOfなしの非常に単純な...

var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];
const isDup = (x,y) => {
   arr.find(it => JSON.stringify(it) == JSON.stringify([x,y])) == undefined ? arr.Push([x,y]) : null
}

console.log(isDup(2,3)) /* Does not add */
console.log(isDup(1,2)) /*Does add*/
console.log(arr) /*Confirmation*/
1
caroham29

プロトタイプを使用して行われた解決策は次のとおりです。そのため、使用法はindexOfに似ていますが、2D配列の場合です。同じ方法で使用します。 arr.indexOf2d([2,3]);

var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];

Array.prototype.indexOf2d = function(item) {
    // arrCoords is an array with previous coordinates converted to strings in format "x|y"
    arrCoords = JSON.stringify(this.map(function(a){return a[0] + "|" + a[1]}));

    // now use indexOf to find item converted to a string in format "x|y"
    return arrCoords.indexOf(item[0] + "|" + item[1]) !== -1;
}
arr.indexOf2d([2,3]); // true
arr.indexOf2d([1,1]); // true
arr.indexOf2d([6,1]); // false
1
Steve Lage

この方法を使用できます

function isArrayItemExists(array , item) {
    for ( var i = 0; i < array.length; i++ ) {
        if(JSON.stringify(array[i]) == JSON.stringify(item)){
            return true;
        }
            }
            return false;
}
0
Dinu

前の答えは言った:

IndexOfを使用して複雑な配列を実行することはできません(各座標をすべて文字列に変換するようにシリアル化しない限り)...

これを行う方法を次に示します。非常に大きなデータセットがある場合、2D配列の複製に依存するため、この手法にはお勧めしません。しかし、合理的なセットの場合、それは簡単です。

次のような一貫した方法を使用して、配列要素を平坦化します。

_// Flatten array into a string, separating elements with a "unique" separator.
function stringle( arr ) {
  return arr.join(' |-| ');
}
_

これは、サブ配列に整数が含まれる例ではやり過ぎですが、より複雑なデータ型の原因となります。 (デフォルトのコンマを使用した場合、コンマを含む文字列要素からは区別できません。)

次に、ターゲット配列を文字列の配列にフラット化できます。

_// Transmogrify arr into a String[], usable with indexOf()
var arrSearch = arr.map(function(row) { return stringle(row); });
_

次に、Array.indexOf()(または他の配列メソッド)を使用して、一致の存在または場所を確認できます。

_if (arrSearch.indexOf( stringle(newArray) ) === -1) ...
_

このスニペットには、複数のデータ型を使用したこのデモが含まれています。

_// Example starting array
var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];

// Flatten array into a string, separating elements with a "unique" separator.
function stringle( arr ) {
  return arr.join(' |-| ');
}

snippet.log("arr: "+JSON.stringify(arr));

// Transmogrify arr into a String[], usable with indexOf()
var arrSearch = arr.map(function(row) { return stringle(row); });

snippet.log("arrSearch: "+JSON.stringify(arrSearch));

var tests = [[0, 9],[1, 2],["pig","cow"],[0,9,"Unicorn"],["pig","cow"]];

for (var test in tests) {
  var str = stringle(tests[test]);
  if (arrSearch.indexOf(str) === -1) {
    arr.Push(tests[test]);
    arrSearch.Push(str);
    snippet.log("Added "+JSON.stringify(tests[test]));
  }
  else {
    snippet.log("Already had "+JSON.stringify(tests[test]));
  }
}

snippet.log("Result: "+JSON.stringify(arr));_
_<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>_
0
Mogsdad