【问题标题】:Search/Filter JavaScript Object Array搜索/过滤 JavaScript 对象数组
【发布时间】:2021-12-16 11:02:48
【问题描述】:

我正在尝试创建一个搜索/过滤功能,允许用户过滤一个 JS 对象数组,该数组返回一个填充了与搜索查询匹配的数据的数组。

我希望能够在一个查询中搜索多个属性,例如;如果我搜索 HKG,它将返回所有 3 个对象,但如果我搜索 HKG 12345,它将返回数组中的第一个对象。

另一个例子是,如果我要搜索 8,它会从匹配查询的 sumOfContainers 属性返回数组中的前 2 个对象,但如果我搜索 8 SAV,它只会返回第一个对象。

results = [];

objects = [
        {laneId:"12345", lane:"HKG-SAV", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"},
        {laneId:"12346", lane:"HKG-FRA", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"},
        {laneId:"12347", lane:"HKG-LAX", equipmentType:"20'STD", sumOfContainers: "9", baseline:"$1234", new:"$1234", newSaving:"$1234"},     
];

const Search = (toSearch) => {
 for(var i=0; i<objects.length; i++) {
   for(key in objects[i]) {
     if(objects[i][key].indexOf(toSearch)!=-1) {
       results.push(objects[i]);
     }
   }
  }
}

我尝试的问题是它会返回重复的数据。我在网上看到了很多帖子,但我发现很难找到寻求类似结果的帖子。

我正在尝试使用原生 JavaScript 来实现这一点。

【问题讨论】:

  • 只需在push 之后添加一个break。别忘了return results
  • Array.from(new Set(results)) 会使结果独一无二。 objects.filter 可能会有所帮助,但这些条件(例如能够搜索“HKG 12345”)有点复杂。
  • @trincot 问题是我仍然想过滤多个属性。这不会创建我正在寻找的确切功能。我还想分解查询,以便它可以按多个属性进行过滤。
  • @Corona,确实如此。想一想:一旦您有一个匹配的键,您就不想检查该 same 对象的其他键。它只是你退出的内部循环。
  • @SebastianSimon 是的,我意识到使数据不重复很容易,但是在单个查询中搜索多个属性会使事情变得非常困难。我想知道我是否应该用空格分隔字符串并重新运行搜索功能,然后过滤掉所有重复项。不确定这是否是更优化的代码。

标签: javascript arrays json search filter


【解决方案1】:

一些问题:

  • 添加重复项是因为添加对象后,您会继续在 same 对象中寻找更多匹配项。因此,如果有任何其他键匹配,相同的对象将被添加两次

  • 当搜索包含空格时,您的描述表明您希望将其视为多个搜索词的分隔符,但您的代码绝不会像那样拆分搜索参数。

  • 您的函数中没有return 语句

  • key 变量未用varletconst 声明

我建议使用filter 解决这个问题:这可以保证您不会得到重复。然后要求所有搜索词都匹配:为此,您可以使用splitevery。然后要求至少有一个与搜索词匹配的键:为此,您可以使用some

不要使用 PascalCase 命名您的搜索函数,而是使用 camelCase(所以 search 而不是 Search)。通常的做法是 PascalCase 是为构造函数/类名保留的。

const search = toSearch => {
 let terms = toSearch.split(" ");
 return objects.filter(object =>
   terms.every(term =>
     Object.values(object).some(value =>
       value.includes(term)
     )
   )
  );
}

【讨论】:

  • 简单干净
  • 我不得不说,我真的很尊重这个答案,简单、干净、优雅,并产生了我想要的结果。我去阅读了每个函数someeveryfilter 的文档。 JavaScript 有时可以很漂亮!
【解决方案2】:

我想出了一个非常糟糕的方法来实现问题中的条件。如果有人可以使这段代码更优化,那就太好了。

  const search = () => {
      let toSearch = document.getElementById("search").value;
      let lanes = this.objects;
      let result = [];
      const filters = toSearch.split(" ");
      for(let i = 0; i <lanes.length; i++) {
        let search = "";
        let isMatched = true;
        for(let key in lanes[i]) {
            search += lanes[i][key] + " ";
        }
        filters.forEach(filter => {
          if(search.indexOf(filter) == -1) {
            isMatched = false;
            break;
          } 
        });
        if(isMatched) {
          result.push(lanes[i]);
        }
      }
      return result;
    }

【讨论】:

  • 此函数的签名与问题中的不同。为什么?
  • @trincot 我重写了函数以省略业务逻辑。
【解决方案3】:

如果你不介意lodash

const _ = require('lodash');

const objects = [
        {laneId:"12345", lane:"HKG-SAV", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"},
        {laneId:"12346", lane:"HKG-FRA", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"},
        {laneId:"12347", lane:"HKG-LAX", equipmentType:"20'STD", sumOfContainers: "9", baseline:"$1234", new:"$1234", newSaving:"$1234"},     
];

const mySearch = (arr, text) => {
  const includesValue = (word, obj) => _.some(obj, (value) => _.includes(value, word));
  const words = _.words(text); 
  return arr
    .filter((obj) => 
      words.every((word) => 
        includesValue(word, obj)
      )
    );
};

console.log(mySearch(objects, 'HKG 12345'));
// [{laneId: '12345', lane: 'HKG-SAV', equipmentType: "20'STD", sumOfContainers: '8', baseline: '$1234', new: '$1234', newSaving: '$1234' }]

console.log(mySearch(objects, '8'));
// [
//   {laneId:"12345", lane:"HKG-SAV", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"},
//   {laneId:"12346", lane:"HKG-FRA", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"},
// ]

console.log(mySearch(objects, '8 SAV'));
// [{laneId: '12345', lane: 'HKG-SAV', equipmentType: "20'STD", sumOfContainers: '8', baseline: '$1234', new: '$1234', newSaving: '$1234' }]

【讨论】:

    猜你喜欢
    • 2017-08-17
    • 2020-05-30
    • 2018-01-16
    • 2018-12-25
    • 2022-01-02
    • 2018-06-21
    • 2012-11-15
    • 2019-11-14
    相关资源
    最近更新 更多