web-dev-qa-db-fra.com

Javascript 2d tableau indexOf

J'ai un tableau 2D comme ça:

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

Chaque index stocke un tableau interne contenant les coordonnées d'un élément.

Comment utiliser Array.indexOf() pour vérifier si le nouveau jeu de coordonnées généré est déjà contenu dans arr? Je veux pousser dans arr si seulement la coordonnée n'est pas un doublon.

Voici ma tentative qui n'a pas fonctionné:

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

Il semble que indexOf() ne fonctionne pas pour les tableaux 2D ...

16
phoeberesnik

Vous ne pouvez pas utiliser indexOf pour faire des tableaux compliqués (sauf si vous le sérialisez en transformant chaque coordonnée en chaîne), vous devrez utiliser une boucle for (ou while) pour rechercher cette coordonnée dans ce tableau en supposant connaître le format du tableau ( dans ce cas c'est 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]);
}

Cette implémentation boucle et saisit chaque valeur. Si vous vous souciez des performances, vous pouvez faire des choses plus compliquées, comme trier le tableau d'origine par le premier index, puis utiliser la recherche binaire sur le premier index. 

Une autre méthode consiste à classer la première coordonnée de chaque élément du tableau dans un objet (comme une table de hachage) et la deuxième valeur dans chacun de ces compartiments afin de réduire les temps de recherche; plus d'infos ici http://en.wikipedia.org/wiki/Bucket_sort

Sinon, c'est probablement suffisant pour ce dont vous avez besoin.

16
user654628

Travailler js fiddle

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

Beaucoup plus d'une manière hacky qu'un simple index de, mais cela fonctionne

6
joegandy

Pas une réponse complète, juste une note de côté qui peut aider.

Utilisez Lodash

Cette méthode vous permettra d'obtenir la position d'une valeur dans un tableau à 2 dimensions

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

Comme mentionné précédemment, vous avez besoin d'une boucle imbriquée pour parcourir le tableau.

2
Mendo

Comme il s'agit d'un tableau à deux dimensions, vous aurez besoin d'une boucle for imbriquée.

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

vous pouvez utiliser cette méthode,

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

Très simple sans 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*/

0
caroham29

Une réponse précédente disait:

Vous ne pouvez pas utiliser indexOf pour faire des tableaux compliqués (à moins que vous ne le sérialisiez en transformant chaque coordonnée en chaîne) ...

Voici comment vous feriez cela. Si vous avez un ensemble de données extrêmement volumineux, je vous déconseille cette technique, car elle repose sur une copie de votre tableau 2D. Mais pour des ensembles raisonnables, c'est simple. 

Utilisez une méthode cohérente pour aplatir des éléments de tableau, tels que:

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

Ceci est excessif pour votre exemple, où les sous-tableaux contiennent des entiers, mais cela représente des types de données plus complexes. (Si nous utilisions une virgule, la valeur par défaut serait indiscernable d'un élément de chaîne contenant une virgule, par exemple.)

Ensuite, le tableau cible peut être aplati en un tableau de chaînes:

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

Ensuite, vous pouvez utiliser Array.indexOf() (ou d’autres méthodes de tableau) pour vérifier la présence ou l’emplacement des correspondances.

if (arrSearch.indexOf( stringle(newArray) ) === -1) ...

Cet extrait de code en contient une démonstration, avec plusieurs types de données.

// 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