Фильтровать массив объектов, чьи свойства содержат значение

Мне интересно, какой самый чистый способ, лучший способ фильтровать массив объектов в зависимости от string keyword. Поиск должен быть выполнен по любым свойствам объекта.

Когда я набираю lea, я хочу пройти через все объекты и все их свойства, чтобы вернуть объекты, содержащие lea

Когда я набираю italy, я хочу пройти через все объекты и все их свойства, чтобы вернуть объекты, содержащие italy.

Я знаю, что есть много решений, но до сих пор я видел некоторые, для которых вам нужно указать свойство, которое вы хотите сопоставить.

ES6 и lodash приветствуются!

  const arrayOfObject = [{
      name: 'Paul',
      country: 'Canada',
    }, {
      name: 'Lea',
      country: 'Italy',
    }, {
      name: 'John',
      country: 'Italy',
    }, ];

    filterByValue(arrayOfObject, 'lea')   // => [{name: 'Lea',country: 'Italy'}]
    filterByValue(arrayOfObject, 'ita')   // => [{name: 'Lea',country: 'Italy'}, {name: 'John',country: 'Italy'}]

Ответы

Ответ 1

Вы можете отфильтровать его и искать только один вхождение строки поиска.

Используемые методы:

  • Array#filter, просто для фильтрации массива с условиями,

  • Object.keys для получения всех имен свойств объекта,

  • Array#some для итерации ключей и выхода из цикла, если он найден,

  • String#toLowerCase для получения сопоставимых значений,

  • String#includes для проверки двух строк, если одна содержит другую.

function filterByValue(array, string) {
    return array.filter(o =>
        Object.keys(o).some(k => o[k].toLowerCase().includes(string.toLowerCase())));
}

const arrayOfObject = [{ name: 'Paul', country: 'Canada', }, { name: 'Lea', country: 'Italy', }, { name: 'John', country: 'Italy' }];

console.log(filterByValue(arrayOfObject, 'lea')); // [{name: 'Lea', country: 'Italy'}]
console.log(filterByValue(arrayOfObject, 'ita')); // [{name: 'Lea', country: 'Italy'}, {name: 'John', country: 'Italy'}]
.as-console-wrapper { max-height: 100% !important; top: 0; }

Ответ 2

Хорошо, когда мы уже знаем, что это не будет поиск объекта с помощью методов, мы можем сделать следующее для сохранения бит по временной сложности:

function filterByValue(array, value) {
  return array.filter((data) =>  JSON.stringify(data).toLowerCase().indexOf(value.toLowerCase()) !== -1);
}

Ответ 3

Используйте Object.keys для прокрутки свойств объекта. Используйте сокращение и фильтр, чтобы сделать код более эффективным:

 const results = arrayOfObject.filter((obj)=>{
     return Object.keys(obj).reduce((acc, curr)=>{
           return acc || obj[curr].toLowerCase().includes(term);
     }, false);
}); 

Где термин - ваш поисковый запрос.

Ответ 4

Вы всегда можете использовать array.filter() а затем array.filter() каждый объект, и если какое-либо из значений соответствует array.filter() значению, верните этот объект.

const arrayOfObject = [{
      name: 'Paul',
      country: 'Canada',
    }, {
      name: 'Lea',
      country: 'Italy',
    }, {
      name: 'John',
      country: 'Italy',
    }, ];
    
let lea = arrayOfObject.filter(function(obj){
  //loop through each object
  for(key in obj){
    //check if object value contains value you are looking for
    if(obj[key].includes('Lea')){
      //add this object to the filtered array
      return obj;
      }
     }
    });
      
console.log(lea);

Ответ 5

function filterByValue(arrayOfObject,words){
  let reg = new RegExp(words,'i');
  return arrayOfObject.filter((item)=>{
     let flag = false;
     for(prop in item){
       if(reg.test(prop)){
          flag = true;
       }  
     }
     return flag;
  });
}

Ответ 6

Один из способов - использовать Array#filter, String#toLowerCase и String#indexOf как String#indexOf ниже.

const arrayOfObject = [{
            name: 'Paul',
            country: 'Canada',
        }, {
            name: 'Lea',
            country: 'Italy',
        }, {
            name: 'John',
            country: 'Italy',
        }];

        function filterByValue(arrayOfObject, term) {
            var ans = arrayOfObject.filter(function(v,i) {
                if(v.name.toLowerCase().indexOf(term) >=0 || v.country.toLowerCase().indexOf(term) >=0) {
                    return true;
                } else false;
            });
            console.log( ans);
        }
        filterByValue(arrayOfObject, 'ita');

Ответ 7

Вот как я буду делать это с помощью lodash:

const filterByValue = (coll, value) =>
  _.filter(coll, _.flow(
    _.values,
    _.partialRight(_.some, _.method('match', new RegExp(value, 'i')))
  ));

filterByValue(arrayOfObject, 'lea');
filterByValue(arrayOfObject, 'ita');

Ответ 8

Этот код проверяет все вложенные значения до тех пор, пока не найдет то, что ищет, затем останавливается и возвращает true в "array.filter" для объекта, в котором он искал (если он ничего не может найти - возвращает false). Когда возвращается значение true, объект добавляется в массив, который возвращает метод array.filter.

const data = [{
    a: "a",
    b: {
      c: "c",
      d: {
        e: "e",
        f: [
          "g",
          {
            i: "i",
            j: {},
            k: []
          }
        ]
      }
    }
  },
  {
    a: "a",
    b: {
      c: "c",
      d: {
        e: "e",
        f: [
          "g",
          {
            i: "findme",
            j: {},
            k: []
          }
        ]
      }
    }
  },
  {
    a: "a",
    b: {
      c: "c",
      d: {
        e: "e",
        f: [
          "g",
          {
            i: "i",
            j: {},
            k: []
          }
        ]
      }
    }
  }
];

function getState(data: any, inputValue: string, state = false) {
  for (const value of Object.values(data)) {
    if (typeof value === 'object' && value !== null && Object.keys(value).length > 0 && state === false) {
      state = getState(value, inputValue, state);
    } else {
      if (state === false) {
        state = JSON.stringify(value).toLowerCase().includes(inputValue.toLowerCase());
      } else {
        return state;
      }
    }
  }
  return state;
}

function filter(data: [], inputValue) {
  return data.filter((element) => getState(element, inputValue));
}

console.log(filter(data, 'findme'));