Возвращаемое значение индекса из метода фильтра javascript

Итак, у меня есть массив объектов в моем угловом контроллере и Я хочу вернуть значение индекса поля в массиве, который имеет соответствующий идентификатор моему параметру. В массиве будет только один объект с соответствующим fieldId..

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

5 ответов


вы не можете вернуть указатель из метода фильтрации.

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

можно использовать forEach

метод filter () создает новый массив со всеми элементами, которые проходят тест, реализованный предоставленной функцией.

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

или даже лучше использовать for как вы не можете остановить forEach, когда вы нашли свой 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.prototype.filter документы:

обратный вызов вызывается с тремя аргументами:

  • значение элемента
  • индекс элемента
  • проходимый объект массива

однако вы, вероятно, должны использовать 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);
});

вторым аргументом для обратного вызова является индекс. Я не могу понять, что вы хотите, чтобы ваша функция делала / возвращала, но если вы добавите , index после function(x, который даст вам доступ к индексу для этой итерации.

работает с имя функции, я не думаю, что вы хотите 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 останавливается с первой итерации, которая возвращает истинное значение, поэтому мы прекратим поиск в первый раз, когда найдем спичка.


некоторые языки могут map коллекция в индексированную коллекцию, где каждый элемент соответствует пара {element, index}. Таким образом, вы можете отобразить/filter/etc, используя любое из этих двух значений.

например, Котлин имеет withIndex и Свифт перечислил.

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

добавить а withIndex метод Array (рекомендуется):

это в основном то же самое, что и обходной путь, но создание многоразовой функции, что делает ее намного чище.

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

Filter не вернет индекс, но вы можете сделать что-то вроде этого.

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