【问题标题】:Return index value from filter method javascript从过滤方法javascript返回索引值
【发布时间】:2014-12-15 14:34:09
【问题描述】:

我的角度控制器中有一组对象。

我想将数组中具有匹配 ID 的字段的索引值返回给我的参数。

数组中只有一个对象与fieldId..匹配。

$scope.indexOfField = function(fieldId) {
  return $scope.model.fieldData.filter(function(x) {
    if (x.Id === fieldId) return // ???????
  });
}

【问题讨论】:

  • 这不是 angujarjs 问题,而是一般的 javascript 问题,所以我会删除 angularjs 标记。但无论如何,这是一个有趣的问题,因为其他语言有处理这个问题的方法。请参阅下面的答案,我在Array 中实现了withIndex 方法。

标签: javascript arrays filter


【解决方案1】:

回调的第二个参数是索引。我不太清楚您希望您的函数执行/返回什么,但如果您在 function(x 之后添加 , index,则您可以访问该迭代的索引。

根据你的函数的 name 工作,我认为你根本不需要 filter:

$scope.indexOfField = function(fieldId) {
    var result = -1;
    $scope.model.fieldData.some(function(x, index) {
        if (x.Id === fieldId) {
            result = index;
            return true;
        }
    });
    return result;
}

Array#some 在第一次返回真值的迭代中停止,因此我们将在第一次找到匹配项时停止搜索。

【讨论】:

  • 此示例中的结果无法访问
  • @AlexScott:“无法访问”是什么意思?回调是一个闭包,闭包可以访问result变量。
  • @Jivings:不,这就是我在示例中使用some 的原因——所以我们一找到匹配项就停止。
  • @Jivings:不关注你。在您发表评论之前,some 位已经存在了大约 10 分钟。但如果评论不再相关,不用担心,只需将其删除即可。
【解决方案2】:

来自Array.prototype.filter 文档:

使用三个参数调用回调:

  • 元素的值
  • 元素的索引
  • 被遍历的 Array 对象

但是,如果您的数组中只有一个实例,您可能应该使用 some 函数(因为它会在找到第一个实例后立即停止),然后使用 indexOf 查找索引:

var field = $scope.model.fieldData.filter(function(x) {
    return x.Id === fieldId;
})[0];
var index = $scope.model.fieldData.indexOf(field);

或者迭代数组直到找到正确的元素:

var index;
$scope.model.fieldData.some(function(x, i) {
    if (x.Id === fieldId) return (index = i);
});

【讨论】:

    【解决方案3】:

    你不能从过滤方法返回索引。

    filter() 方法创建一个包含所有通过的元素的新数组 由提供的函数实现的测试。

    您可以使用forEach

    $scope.indexOfField = function(fieldId) {
        var i;
        return $scope.model.fieldData.forEach(function(x, index) {
            if (x.Id === fieldId) {
                i = index;
            }
        });
        // use i
    }
    

    或者更好地使用for,因为当你找到你的id时你不能停止forEach。

    $scope.indexOfField = function(fieldId) {
        var fieldData = $scope.model.fieldData, 
            i = 0, ii = $scope.model.fieldData.length;
        for(i; i < ii; i++) if(fieldData[i].Id === fieldId) break;
        // use i
    }
    

    【讨论】:

    • 这将遍历每个元素,而不是在找到正确的元素后停止。
    • 谢谢。对 for 循环进行了一些更改,它可以满足我的需求
    • "i" 可能不是在遍历整个数组且未找到所查找对象的情况下所需的索引
    【解决方案4】:

    过滤器不会返回索引,但你可以这样做。

    $scope.indexOfField = function(fieldId) {
        $scope.model.fieldData.filter(function(x, i) {
            if (x.Id === fieldId) {
                var indexOfField = i;
            }
        });
        return indexOfField;
    };
    

    【讨论】:

      【解决方案5】:

      某些语言可以将一个集合map 转换为一个索引集合,其中每个元素都映射到一对{element, index}。这样你就可以使用这两个值中的任何一个来映射/过滤/等。

      例如,Kotlin 有withIndex,Swift 有enumerated。

      Javascript 没有那个方法,AFAIK。但您可以轻松构建自己的或使用解决方法。

      解决方法(不推荐)

      // Turn an array of elements into an array of {value, index}
      const indexedArray = array.map((v,i) => ({value:v, index:i}));
      // Now I can filter by the elem but keep the index in the result
      const found = array.filter(x => x.value === someValue)[0];
      if (found) {
          console.log(`${found.value} found at index ${found.index}`);
      }
      
      // One-liner for the question scenario, using some new js features.
      // Note that this will fail at the last ".i" if the object is not found.
      const index = fieldData.map((v,i) => ({v,i})).filter(x => x.v.id == fieldId)[0].i
      

      给Array添加一个withIndex方法(推荐):

      这与解决方法基本相同,但创建了一个可重用的函数,这使得它更加简洁。

      Array.prototype.withIndex = function() {
          return this.map((v,i) => ({value: v, index: i}))
      };
      
      // Now the one-liner would be:
      const index = fieldData.withIndex().filter(x => x.value.id == fieldId)[0].index;
      
      // Better, with null checking:
      const found = fieldData.withIndex().filter(x => x.value.id == fieldId)[0];
      if (found) {
          console.log(`${found.value} found at index ${found.index}`);
      }
      

      【讨论】:

        【解决方案6】:

        数组(查找多个索引)方法

        [10, 7, 13, 15, 230].map((e,i) => e > 13 ? i : undefined).filter(x => x) 
              //returns [3, 4](*** RETURNS multiple indexes ***)
              //FILTER (is simply just REMOVING the UNDEFINED elements (which are FALSY and considered the same as FALSE)
        

        否则你会得到...

        [10, 7, 13, 15, 230].map((e,i) => e > 13 ? i : undefined)  //returns [undefined, undefined, undefined, 3, 4]
        

        返回多个索引(替换 findIndex 方法)

        [1, 1, 2, 2, 2, 3, 4, 5].map((e,i) => e === 2 ? i : undefined).filter(x => x) //returns [2, 3, 4]
        

        返回多个值(替换查找方法)

        [5, 12, 8, 130, 44].map((e,i) => e > 13 ? e : undefined).filter(x => x) // returns [130, 44]
        

        【讨论】:

        • index = 0 怎么样?它是虚假的,所以它会被过滤掉。你需要x =&gt; x !== undefined
        • .....filter(function(x){ return (x||x>=0)?true:false;})
        • filter(x => x !== undefined) 使用索引 0
        【解决方案7】:

        .findIndex() 方法返回满足函数给定条件的数组的第一个元素的索引。如果函数为数组的所有元素返回false,则结果为-1。

        See the documentation here.

        在我的示例中,x 是每次迭代的一个项目,我对我的条件使用交叉函数。

        const datas = [];
        const fieldId = 5;
        let index = datas.findIndex( x => x.Id === fieldId );
        

        【讨论】:

        • 请在代码中添加一些描述。
        • 欢迎来到 Stack Overflow!虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的答案添加解释并说明适用的限制和假设。
        • 我觉得最后一行应该是:let index = datas.findIndex( x =&gt; x === fieldId );
        • 工作得很好,谢谢!这正是我所需要的
        【解决方案8】:

        您不能直接返回索引,但可以设置'thisArg' parameter 并在其中设置数据。这比全局变量更干净。

        var data = {
            indexes: []
        };
        var myArray = [1,2,3,4,5,6,7,8,9,10];
        
        myArray.filter(function (element, index) {
            if (element%2 == 0) {
                this.indexes.push(index);
                return true;
            }
        }, data);
        
        console.log(data.indexes); // [1, 3, 5, 7, 9]
        data.indexes.forEach(function(value) {
            console.log(myArray[value]);
        }); // 2, 4, 6, 8, 10
        

        【讨论】:

        • 这确实帮助了我的情况,获得了结果数组以及它们在原始数组中的索引位置。 (删除它们)谢谢
        【解决方案9】:
        function modifyArray(nums) {
        let newNums = nums.filter((num,index) => {
                return num = num % 2 ? num * 3 : num * 2; 
            })
          return newNums;
        }
        

        这里的索引是你要找的增量值。

        【讨论】:

        • 这根本不能回答问题。
        【解决方案10】:

        使用findIndex。 您可以使用此功能。当条件最先满足时,返回索引。

        https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

        【讨论】:

        • 这应该是相关的答案!
        【解决方案11】:

        如果只返回一个对象,您可以简单地使用原始数组来引用返回的对象。

        由于过滤器返回一个数组,所以可以这样做

        $scope.indexOfField = function(fieldId) {
            var filteredArray = $scope.model.fieldData.filter(function(x) {
                return x.Id === fieldId
            });
        
            var desiredObject = filteredArray[0]
            return $scope.model.fieldData.indexOf(desiredObject);
        }
        

        【讨论】:

          【解决方案12】:
          $scope.indexOfField = function(fieldId) {
            let index;
            $scope.model.fieldData.filter((x, i) => {
              if (x.Id === fieldId) index = i;
              return x.Id === fieldId;
            });
            return index;
          }
          

          【讨论】:

            【解决方案13】:

            试试flatMap(),有或没有i。

            [5, 12, 8, 130, 44].flatMap((e, i) => (e > 13 ? e : [])); // returns [130, 44]
            

            【讨论】:

              【解决方案14】:
              ['ab', 'cd', 'ef', 'id', 'junk', 'dummy','name'].map((x, ndx)=>['id', 'name'].includes(x)?ndx:'').filter(e=>e)
              

              结果:(2) [3, 6]

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2022-09-25
                • 2022-06-12
                • 2011-09-06
                • 2021-11-27
                • 2021-06-02
                • 2018-10-05
                • 2021-01-30
                • 2012-04-10
                相关资源
                最近更新 更多