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

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

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

Ответ 1

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

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, когда вы нашли свой идентификатор.

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

Ответ 2

Из документации 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);
});

Ответ 3

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

Ответ 4

МЕТОД ARRAY (НАЙТИ НЕСКОЛЬКО ИНДЕКСОВ)

[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]

Ответ 5

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

Например, Kotlin имеет withIndex, а Swift перечислил.

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

Ответ 6

Метод findIndex возвращает индекс первого элемента массива, который удовлетворяет условию, заданному функцией. Если функция возвращает false для всех элементов массива, результатом будет -1.

Смотрите документацию здесь
В моем примере x - это элемент для каждой итерации, и я использую перекрестную функцию для моего условия.

Я надеюсь, что помогу тебе

const datas = [];
const fieldId = 5;
let index = datas.findIndex(x => x.Id === fieldId);

Ответ 7

Вы не можете напрямую вернуть индекс, но вы можете установить параметр thisArg и установить данные внутри него. Это чище, чем глобальная переменная.

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

Ответ 8

function modifyArray(nums) {
let newNums = nums.filter((num,index) => {
        return num = num % 2 ? num * 3 : num * 2; 
    })
  return newNums;
}

Здесь индекс - это значение приращения, которое вы ищете.

Ответ 9

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

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