Javascript 任何属性都包含值的对象的过滤器数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44312924/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:26:43  来源:igfitidea点击:

Filter array of objects whose any properties contains a value

javascriptarrayslodash

提问by Léo Coco

I'm wondering what is the cleanest way, better way to filter an array of objects depending on a string keyword. The search has to be made in any properties of the object.

我想知道什么是最干净的方法,根据string keyword. 必须在对象的任何属性中进行搜索。

When I type leaI want to go trough all the objects and all their properties to return the objects that contain lea

当我输入时,lea我想遍历所有对象及其所有属性以返回包含的对象lea

When I type italyI want to go trough all the objects and all their properties to return the objects that contain italy.

当我键入时,italy我想遍历所有对象及其所有属性以返回包含italy.

I know there are lot of solutions but so far I just saw some for which you need to specify the property you want to match.

我知道有很多解决方案,但到目前为止我只看到了一些您需要指定要匹配的属性的解决方案。

ES6and lodashare welcome !

ES6lodash欢迎!

  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'}]

回答by Nina Scholz

You could filter it and search just for one occurence of the search string.

您可以过滤它并只搜索搜索字符串的一次出现。

Methods used:

使用的方法:

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

回答by binariedMe

Well when we already know that its not going to be a search on an object with methods, we can do the following for saving bit on time complexity :

好吧,当我们已经知道它不会使用方法搜索对象时,我们可以执行以下操作以节省时间复杂度:

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

回答by Vincent Ramdhanie

Use Object.keys to loop through the properties of the object. Use reduce and filter to make the code more efficient:

使用 Object.keys 循环遍历对象的属性。使用 reduce 和 filter 使代码更高效:

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

Where term is your search term.

其中 term 是您的搜索词。

回答by Josan Iracheta

You can always use array.filter()and then loop through each object and if any of the values match the value you are looking for, return that object.

您始终可以使用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);

回答by Noob

This code checks all the nested values until it finds what it's looking for, then stops and returns true to the "array.filter" for the object it was searching inside(unless it can't find anything - returns false). When true is returned, the object is added to the array that the "array.filter" method returns.

此代码检查所有嵌套值,直到找到它要查找的内容,然后停止并将 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'));

If you need to search for objects that contain multiple keywords, to narrow down the filtered objects further, which makes the filter even more user friendly.

如果您需要搜索包含多个关键字的对象,可以进一步缩小过滤对象的范围,使过滤器更加人性化。

const data = [{
    a: "a",
    b: {
      c: "c",
      d: {
        e: "findme2",
        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: "findme2",
        f: [
          "g",
          {
            i: "findme",
            j: {},
            k: []
          }
        ]
      }
    }
  }
];

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

function checkState(element: any, inputValue: string) {
  const filterValues = inputValue.trim().split(' ');
  const states: boolean[] = [];

  for (let index = 0; index < filterValues.length; index++) {
    states[index] = getState(element, filterValues[index]);
  }

  return states.every(state => state === true);
}

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

console.log(filter(data, 'findme')); // gets all objects that contain "findme"

console.log(filter(data, 'findme findme2')); // gets all objects that contain "findme" and "findme2"

回答by Pankaj Shukla

One way would be to use Array#filter, String#toLowerCaseand String#indexOflike below.

一种方法是使用Array#filterString#toLowerCaseString#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');

回答by Adam Boduch

Here's how I would do it using lodash:

下面是我将如何使用 lodash 做到这一点:

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

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

回答by Kermit

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