Return index value from filter method javascript

JavascriptArraysFilter

Javascript Problem Overview


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 // ???????
  });
}

Javascript Solutions


Solution 1 - Javascript

The .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 );

Solution 2 - Javascript

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
}

Solution 3 - Javascript

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);
});

Solution 4 - Javascript

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]

Solution 5 - Javascript

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.

Solution 6 - Javascript

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

Solution 7 - Javascript

Use the findIndex. You can use this function. When the condition is met first, the index is returned.

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

Solution 8 - Javascript

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}`);
}

Solution 9 - Javascript

Try flatMap(), with or without i.

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

Solution 10 - Javascript

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);
}

Solution 11 - Javascript

['ab', 'cd', 'ef', 'id', 'junk', 'dummy','name'].map((x, ndx)=>['id', 'name'].includes(x)?ndx:'').filter(e=>e)

result: (2) [3, 6]

Solution 12 - Javascript

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;
};

Solution 13 - Javascript

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

Solution 14 - Javascript

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionalsco77View Question on Stackoverflow
Solution 1 - Javascriptquime parleView Answer on Stackoverflow
Solution 2 - JavascriptRuben NagogaView Answer on Stackoverflow
Solution 3 - JavascriptJivingsView Answer on Stackoverflow
Solution 4 - JavascriptDean JonesView Answer on Stackoverflow
Solution 5 - JavascriptT.J. CrowderView Answer on Stackoverflow
Solution 6 - JavascriptJustAnotherDeveloperView Answer on Stackoverflow
Solution 7 - JavascriptA.R NaseefView Answer on Stackoverflow
Solution 8 - JavascriptFerran MaylinchView Answer on Stackoverflow
Solution 9 - JavascriptJonyDView Answer on Stackoverflow
Solution 10 - JavascriptGabriel GView Answer on Stackoverflow
Solution 11 - JavascriptKrishna MurthyView Answer on Stackoverflow
Solution 12 - JavascriptMattView Answer on Stackoverflow
Solution 13 - JavascriptJakub KellerView Answer on Stackoverflow
Solution 14 - JavascriptFoysal Ahmed EmonView Answer on Stackoverflow