admin管理员组文章数量:1134247
I have an array of objects in my angular controller.
I want to return the value of the index of the field within the array which has a matching ID to my parameter.
There will only be one object in the array with a matching fieldId
..
$scope.indexOfField = function(fieldId) {
return $scope.model.fieldData.filter(function(x) {
if (x.Id === fieldId) return // ???????
});
}
I have an array of objects in my angular controller.
I want to return the value of the index of the field within the array which has a matching ID to my parameter.
There will only be one object in the array with a matching fieldId
..
$scope.indexOfField = function(fieldId) {
return $scope.model.fieldData.filter(function(x) {
if (x.Id === fieldId) return // ???????
});
}
Share
Improve this question
edited Apr 16, 2021 at 18:50
serraosays
7,8293 gold badges38 silver badges67 bronze badges
asked Oct 20, 2014 at 14:50
user4079725user4079725
1
|
15 Answers
Reset to default 103The .findIndex()
method returns the index of the first element of the array that satisfies a condition given by a function. If the function returns false
for all elements of the array, the result is -1
.
See the documentation here.
In my example, x
is an item for each iteration and I use cross function for my condition.
const datas = [];
const fieldId = 5;
let index = datas.findIndex( x => x.Id === fieldId );
You can't return index from filter method.
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
You can use forEach
$scope.indexOfField = function(fieldId) {
var i;
return $scope.model.fieldData.forEach(function(x, index) {
if (x.Id === fieldId) {
i = index;
}
});
// use i
}
or even better to use for
as you can't stop forEach when you have found your id.
$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
}
ARRAY (FIND MULTIPLE INDEXES) METHOD
[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)
otherwise you'll get...
[10, 7, 13, 15, 230].map((e,i) => e > 13 ? i : undefined) //returns [undefined, undefined, undefined, 3, 4]
RETURN MULTIPLE INDEXES (replaces findIndex METHOD)
[1, 1, 2, 2, 2, 3, 4, 5].map((e,i) => e === 2 ? i : undefined).filter(x => x) //returns [2, 3, 4]
RETURN MULTIPLE VALUES (replaces find METHOD)
[5, 12, 8, 130, 44].map((e,i) => e > 13 ? e : undefined).filter(x => x) // returns [130, 44]
From the Array.prototype.filter
documentation:
callback is invoked with three arguments:
- the value of the element
- the index of the element
- the Array object being traversed
However you should probably be using the some
function if there is only one instance in your array (as it will stop as soon as it finds the first occurrence), and then find the index using indexOf
:
var field = $scope.model.fieldData.filter(function(x) {
return x.Id === fieldId;
})[0];
var index = $scope.model.fieldData.indexOf(field);
Or iterate the array until you find the correct element:
var index;
$scope.model.fieldData.some(function(x, i) {
if (x.Id === fieldId) return (index = i);
});
The second argument to your callback is the index. I can't quite make out what you want your function to do/return, but if you add , index
after function(x
, that will give you access to the index for that iteration.
Working from the name of your function, I don't think you want filter
at all:
$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
stops as of the first iteration that returns a truthy value, so we'll stop searching the first time we find a match.
Use the findIndex
method - Array.prototype.findIndex()
.
When the condition is met first, the index is returned.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
You cannot return directly the index but you can set the 'thisArg' parameter and set data inside it. This is cleaner than a global variable.
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
Try flatMap()
, with or without i
.
[5, 12, 8, 130, 44].flatMap((e, i) => (e > 13 ? e : [])); // returns [130, 44]
You most definitely can (ahem, guy who got accepted answer)
const polyfillter = (arr,condition) => arr.map( (e,i) => condition ? i : -1).filter(e=>e>=0)
Pass in an array, and your condition, and get back matching keys.
example
mynewstuff = polyfillter(myoldcrud, "e.length > 5")
Some languages can map
a collection into an indexed collection where each element is mapped to a pair of {element, index}
. That way you can map/filter/etc using any of those two values.
For example, Kotlin has withIndex and Swift has enumerated.
Javascript doesn't have that method, AFAIK. But you can easily build yours or use a workaround.
Workaround (not recommended)
// 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
Add a withIndex
method to Array
(recommended):
This is basically the same as the workaround, but creating a reusable function, which makes it much cleaner.
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}`);
}
If there is only one object returned you can simply use the original array to refer to the returned object.
Since filter returns an array, you can do as follows
$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);
}
['ab', 'cd', 'ef', 'id', 'junk', 'dummy','name'].map((x, ndx)=>['id', 'name'].includes(x)?ndx:'').filter(e=>e)
result: (2) [3, 6]
Filter will not return the index, but you can do something like this.
$scope.indexOfField = function(fieldId) {
$scope.model.fieldData.filter(function(x, i) {
if (x.Id === fieldId) {
var indexOfField = i;
}
});
return indexOfField;
};
$scope.indexOfField = function(fieldId) {
let index;
$scope.model.fieldData.filter((x, i) => {
if (x.Id === fieldId) index = i;
return x.Id === fieldId;
});
return index;
}
function modifyArray(nums) {
let newNums = nums.filter((num,index) => {
return num = num % 2 ? num * 3 : num * 2;
})
return newNums;
}
Here the index is the increment value you are looking for.
本文标签: arraysReturn index value from filter method javascriptStack Overflow
版权声明:本文标题:arrays - Return index value from filter method javascript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736802270a1953539.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
angularjs
tag. But it's an interesting question anyway, because other languages have methods to handle this. See my answer below, where I implement a withIndex method inArray
. – Ferran Maylinch Commented May 3, 2018 at 20:46