在所有属性值上过滤对象数组

8
我很惊讶我没能找到与我的问题相关的任何内容。我正在寻找一种快速的方法,根据用户文本输入来过滤我的对象数组。
假设我有这个数组:
let data = [{
  "id": 1,
  "first_name": "Jean",
  "last_name": "Owens",
  "email": "jowens0@google.ru",
  "gender": "Female"
}, {
  "id": 2,
  "first_name": "Marie",
  "last_name": "Morris",
  "email": "mmorris1@engadget.com",
  "gender": "Female"
}, {
  "id": 3,
  "first_name": "Larry",
  "last_name": "Wallace",
  "email": "lwallace2@example.com",
  "gender": "Male"
}];

用户输入 "s",预期结果应为:

let result = [{
  "id": 1,
  "first_name": "Jean",
  "last_name": "Owens",
  "email": "jowens0@google.ru",
  "gender": "Female"
}, {
  "id": 2,
  "first_name": "Marie",
  "last_name": "Morris",
  "email": "mmorris1@engadget.com",
  "gender": "Female"
}]

我可以这样使用过滤函数:

let = searchText = "s";
    let result = data.filter(object=>{
      for (var property in object) {
        if (object.hasOwnProperty(property)) {
          return object[property].toString().toLowerCase().indexOf(searchText) !== -1;
        }
      }
    });

我想知道这个解决方案是否有更好的替代方法?

--这是一个有效的JsFiddle,感谢KoolShams

--用于基准测试的Plunker(使用2k数据进行测试)


在这种情况下,使用“l”进行搜索会返回所有数据,因为“l”是“男性”或“女性”中的一部分...... 奇怪的行为 - kevin ternet
是的?这正是我想要的 :) - Yann Thibodeau
1
为您创建了一个小工具。https://jsfiddle.net/d8mhtjs5/5/ - shams.kool
感谢@KoolShams提供的示例代码,我将把它添加到问题中! - Yann Thibodeau
3个回答

8
你可以使用Object.keys()some()代替。

let data = [{
  "id": 1,
  "first_name": "Jean",
  "last_name": "Owens",
  "email": "jowens0@google.ru",
  "gender": "Female"
}, {
  "id": 2,
  "first_name": "Marie",
  "last_name": "Morris",
  "email": "mmorris1@engadget.com",
  "gender": "Female"
}, {
  "id": 3,
  "first_name": "Larry",
  "last_name": "Wallace",
  "email": "lwallace2@example.com",
  "gender": "Male"
}];

var result = data.filter(function(o) {
  return Object.keys(o).some(function(k) {
    return o[k].toString().toLowerCase().indexOf('s') != -1;
  })
})

console.log(result)


不错,我喜欢它,有些函数会比循环更快吗? - Yann Thibodeau
不确定这是否是正确的测试方式,但似乎循环总是更快 https://jsfiddle.net/Lg0wyt9u/1253/ - Nenad Vracar
1
我已经用2k的数据和几个不同的字符串进行了测试,循环明显更快:https://plnkr.co/edit/i1it9PZ7WMzwpsopT7pS?p=preview - Yann Thibodeau

1
你可以使用 Object.keys 并省略 hasOwnProperty
这个解决方案使用 箭头函数

let data = [{ "id": 1, "first_name": "Jean", "last_name": "Owens", "email": "jowens0@google.ru", "gender": "Female" }, { "id": 2, "first_name": "Marie", "last_name": "Morris", "email": "mmorris1@engadget.com", "gender": "Female" }, { "id": 3, "first_name": "Larry", "last_name": "Wallace", "email": "lwallace2@example.com", "gender": "Male" }],
    searchText = "s",
    result = data.filter(o => 
        Object.keys(o).some(k => 
            o[k].toString().toLowerCase().indexOf(searchText) !== -1));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

为了更好的性能,如果数组中的对象是统一的,你可以提前把键存储起来并迭代这些键,而不是对数组中所有对象使用Object.keys

let data = [{ "id": 1, "first_name": "Jean", "last_name": "Owens", "email": "jowens0@google.ru", "gender": "Female" }, { "id": 2, "first_name": "Marie", "last_name": "Morris", "email": "mmorris1@engadget.com", "gender": "Female" }, { "id": 3, "first_name": "Larry", "last_name": "Wallace", "email": "lwallace2@example.com", "gender": "Male" }],
    keys = Object.keys(data[0]),
    searchText = "s",
    result = data.filter(o => 
        keys.some(k => 
            o[k].toString().toLowerCase().indexOf(searchText) !== -1));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


我将您的解决方案添加到我的基准测试中,然后将其添加到问题中,循环仍然是最快的。 - Yann Thibodeau

1

好的,您可以使用任何lodash的集合相关函数来操作对象,它会迭代值。此外,您可以直接对任何字符串、数字或布尔值使用_.toLower,它将处理所有边角情况,因此如果您想要一个更简单的解决方案和良好结构化的代码,那么请看这里:

data.filter(o=>_.some(o, v => _.toLower(v).indexOf('s')>-1))

这是一个可工作的示例:

let data = [{
  "id": 1,
  "first_name": "Jean",
  "last_name": "Owens",
  "email": "jowens0@google.ru",
  "gender": "Female"
}, {
  "id": 2,
  "first_name": "Marie",
  "last_name": "Morris",
  "email": "mmorris1@engadget.com",
  "gender": "Female"
}, {
  "id": 3,
  "first_name": "Larry",
  "last_name": "Wallace",
  "email": "lwallace2@example.com",
  "gender": "Male"
}];

var sTxt = 's';

var res = data.filter(o=>_.some(o, v =>_.toLower(v).indexOf(sTxt)>-1))

console.log('Result: ', JSON.stringify(res,null,'    '));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接