从过滤方法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 => 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 => 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()使用方法