从过滤方法javascript返回索引值

Posted

技术标签:

【中文标题】从过滤方法javascript返回索引值【英文标题】:Return index value from filter method 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 方法。 【参考方案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]

【讨论】:

以上是关于从过滤方法javascript返回索引值的主要内容,如果未能解决你的问题,请参考以下文章

javascript中slice(),splice(),split(),substring(),substr()使用方法

JavaScript常用数组元素搜索或过滤的四种方法

JavaScript常用数组元素搜索或过滤的四种方法

JavaScript常用数组元素搜索或过滤的四种方法

如何在 C# 字典中按值索引过滤项目?

将数据从 Java/JSF2 bean 传递到 Javascript/jQuery 组件作为返回值的最佳方法