Каков наилучший способ получения индекса из огромного массива объектов JSON, который совпадает с массивом объектов JSON

#arrays #json #jsonobjectrequest #json-arrayagg

Вопрос:

Я хочу знать лучший способ получения индексов из огромного (длина массива почти 150 000) массива JSON объектов JSON, который совпадает с массивом объектов JSON.

В настоящее время я использую цикл for для выполнения этой работы, но это занимает от 3 до 4 минут времени. Есть ли какой-нибудь лучший способ улучшить производительность? Ниже приведен пример, иллюстрирующий мое требование.

 var hugeArray = [
    {firstName:"John", lastName:"Doe", age:21},
    {firstName:"Abraham", lastName:"Lincoln", age:46},
    {firstName:"Andy", lastName:"Crossland", age:32},
    .
    .
    .
    {firstName:"Jimmy", lastName:"Fletcher", age:65}
];
 

Предположим, что длина огромного массива составляет 150 000. И у меня есть еще один массив JSON(matchArray) длиной 15 000.

 var matchArray = [
    {firstName:"John", lastName:"Doe"},
    {firstName:"Andy", lastName:"Crossland"},
    .
    .
    .
    {firstName:"Jimmy", lastName:"Fletcher"}
];
 

Мне нужны индексы из hugeArray, которые совпадают с matchArray.

Например, из приведенных выше данных, в matchArray есть список объектов, и эти объекты должны быть сопоставлены с объектами в массиве. Если совпадет, то верните индексы hugeArray. Результат приведенного выше примера будет таким, как показано ниже.

[0,2,...,150000]

Для этого я написал функцию, и эта функция возвращает индекс hugeArray. Если объект matchArray совпадает с hugeArray, то возвращает индекс совпадающего hugeArray, в противном случае возвращает -1.

 //returns -1 if no matched objects found otherwise returns index of searchArray that matched with obj.
//searchArray : Array that used to search in and return matched index.
//obj : JSON object which is used to match in with searchArray objects.
function getArrayIndex(searchArray,obj){
    var index = -1;
    for(var i=0,searchArrayLen=searchArray.length;i<searchArrayLen;i  ){
        var keyMatch = true;
        for(var key in obj){
            if(obj[key].trim() !== searchArray[i][key].trim()){
                keyMatch = false;
                break;
            }
        }
        if(keyMatch){
            index = i;
            return index;
        }
    }
    return index;
}
 

Написал ниже функцию getIndexes, чтобы вызвать выше функцию getArrayIndex.

 //returns array of indexes.
function getIndexes(hugeArray,matchArray){
    var indexArray = [];
    var matchArrayLen = matchArray.length;
    for(var i=0; i<matchArrayLen; i  ){
        var matchIndex = getArrayIndex(hugeArray,matchArray[i]);
        if(matchIndex !== -1){
            indexArray.push(matchIndex);
        }
    }
    return indexArray;
}
 

Наконец, вызвав функцию getIndexes, предоставив все совпадающие индексы в формате массива.

Например,

 var index = getIndexes(hugeArray,matchArray);
console.log(index);// This prints an array that contains matched indexes.
//For above data, output will be like [0,2,...,150000].
 

Комментарии:

1. Пожалуйста, не используйте здесь индийские слова, такие как лакх / лак. Люди, живущие в другом месте, не поймут их.

2. @JamesZ Хорошо, спасибо, что дали мне знать и исправили вопрос.

Ответ №1:

Для этого можно использовать объект карты.

 let theMap = new Map(hugeArray.map((item, index) => [item.firstName   " "   item.lastName, index]));

let result = matchArray.map(item => theMap.get(item.firstName   " "   item.lastName))
  .filter(i => i !== undefined)
 

Это предполагает firstName наличие или lastName отсутствие пробелов. Используйте другой символ, если они могут содержать пробелы.

Если hugeArray есть дубликаты:

 let theMap = new Map();
hugeArray.forEach((item, index) => {
  let key = item.firstName   " "   item.lastName;
  let value = theMap.get(key);
  if (value === undefined)
    theMap.set(key, [index]);
  else
    value.push(index);
});

let result = matchArray.flatMap(item => theMap.get(item.firstName   " "   item.lastName))
  .filter(i => i !== undefined);
 

Если нам нужен отсортированный результат, когда hugeArray есть дубликаты:

 let result = matchArray.flatMap(item => theMap.get(item.firstName   " "   item.lastName))
      .filter(i => i !== undefined).sort();
 

Комментарии:

1. Потрясающе, спасибо за ответ. Твое решение сделало мой день лучше!. Отлично работает. Теперь работа выполнена за 3 секунды, в то время как это было 3-4 минуты назад.

2. решение работает для уникального совпадения, а не для дубликатов. Допустим, что делать, если hugeArray имеет дубликаты и сопоставлен с matchArray ? Мне нужны все индексы из hugeArray, которые совпадают, но приведенное выше решение дает только первое совпадение с последним индексом.

3. Снова потрясающе 🙂 Работает идеально ! Трудно это понять else condition . Не могли бы вы, пожалуйста, объяснить, как настроить объект карты для hugeArray ? То, что я заметил, таково… при установке в объект карты мы выполняем проверку дубликатов. Если найден дубликат, вставьте только индекс в существующий элемент объекта карты, в противном случае вставьте в объект карты как новую запись.

4. @user2388677 Для каждого ключа мы помещаем массив на карту. В этой if части мы помещаем массив размером 1 (с индексом в качестве единственного элемента) на карту для первого появления ключа. В этой else части мы добавляем текущий индекс в конец указанного массива для второго и следующих вхождений ключа.