【问题标题】:Javascript 2d array indexOfJavascript 二维数组 indexOf
【发布时间】:2014-09-16 13:38:48
【问题描述】:

我有一个这样的二维数组:

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() 不适用于二维数组...

【问题讨论】:

    标签: javascript arrays 2d indexof


    【解决方案1】:

    你不能使用 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]);
    }
    

    此实现循环并获取每个值。如果您关心性能,您可以做更复杂的事情,例如按第一个索引对原始数组进行排序,然后在第一个索引上使用二进制搜索。

    另一种方法是将数组中每个项目的第一个坐标存储在一个对象(如哈希表)中,并将第二个值存储在每个存储桶中,以减少搜索时间;更多信息在这里http://en.wikipedia.org/wiki/Bucket_sort

    否则这可能足以满足您的需要。

    【讨论】:

      【解决方案2】:

      Working js fiddle

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

      比简单的索引更多的是一种 hacky 方式,但它确实有效

      【讨论】:

        【解决方案3】:

        不是一个完整的答案,只是一个可能有帮助的旁注。

        使用 Lodash

        这个方法会得到一个值在二维数组中的位置

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

        如前所述,您需要一个嵌套循环来遍历数组。

        【讨论】:

        • 我更喜欢把return el[0] == 'cow'换成return el.includes('cow')
        • 我复制粘贴并尝试了let b = _.findIndex(a, function(el) { return el[0] == 'cow'; }); 并得到ReferenceError: _ is not defined
        • 下划线 _ 是对 Lodash 的引用。 lodash.com
        • @Mendo 我怎样才能有条件地根据这个改变样式?
        【解决方案4】:

        没有 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*/

        【讨论】:

        • 我确实想要一个索引,所以我使用了:const find = this.pointList.findIndex(it =&gt; JSON.stringify(it) === JSON.stringify(item));
        【解决方案5】:

        因为这是一个二维数组,所以需要一个嵌套的 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;
        }
        

        【讨论】:

          【解决方案6】:

          这是一个使用原型完成的解决方案,因此用法类似于 indexOf 但用于二维数组。使用方式相同: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
          

          【讨论】:

            【解决方案7】:

            这是我实现的

            getIndexOfArray(array: any[], findArray: any[]): number{
              let index = -1;
              array.some((item, i)=>{
                if(JSON.stringify(item) === JSON.stringify(findArray)) {
                  index = i;
                  return true;
                }
              });
              return index;
            }
            

            这里array 是我们需要索引的数组,findArray 是要返回其索引的数组。
            注意:此函数将只返回findArray数组洞察array数组的第一次出现。

            【讨论】:

              【解决方案8】:

              之前的回答说:

              你不能用 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) ...
              

              这个 sn-p 包含一个演示,具有多种数据类型。

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

              【讨论】:

                【解决方案9】:

                你可以用这个方法,

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

                【讨论】:

                  【解决方案10】:

                  ES2020 更新

                  如果你能够支持 ES2020,你可以使用新的?. operator(可选链操作符)。它可以用于二维数组,如下所示:

                  const arr = [[1,2],[3,4]];
                  
                  if ( ! arr[5]?.[6] ) {
                    console.log("Index out of bounds");
                  }
                  
                  if ( arr[0]?.[0] ) {
                    console.log("Index in bounds");
                  }
                  

                  如果您尝试使用可选链接运算符访问任何 undefined 的属性,它将评估为 undefined 而不是抛出类似 Cannot read property 'foo' of 'undefined' 的东西。


                  文档

                  【讨论】:

                    【解决方案11】:

                    在二维数组中查找元素索引的数组方法:

                    要从二维数组中获取元素的索引,您可以遍历数组的第一层并在第二层使用 indexOf()。我制作了一个类似 indexOf 的数组原型,但是对于 2D 数组并且没有它的第二个参数 (IndexOf(_, fromIndex)):

                    Array.prototype.twoDIndexOf = function(element){
                      if (this === null || this === undefined)
                        throw TypeError("Array.prototype.indexOf called on null or undefined")
                      for(let i = 0; i < this.length; i++){
                        const curr = this[i]
                        if(curr.includes(element))
                          return [i, curr.indexOf(element)];
                      }
                      return -1;
                    }
                    
                    
                    const exArray =  [
                      ['1', '2', '3'],
                      ['4', '5', '6'],
                      ['7', '8', '9'],
                      ['', '0', ''],
                    ]
                    
                    console.log(exArray.twoDIndexOf('7')); // [2, 0]
                    console.log(exArray.twoDIndexOf('6')); // [1, 2]
                    console.log(exArray.twoDIndexOf('')); // [3, 0]
                    console.log(exArray.twoDIndexOf('x')); // -1

                    注意,该方法返回元素的第一个索引,这意味着如果元素在同一个数组中重复多次,则返回的值是它的第一个位置。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2010-09-16
                      • 2010-12-30
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-01-25
                      • 1970-01-01
                      相关资源
                      最近更新 更多