JS:搜索另一个

时间:2017-11-21 16:57:06

标签: javascript regex angular typescript filter

我有一个列表对象,我从Web服务加载。我的清单以这种形式出现:

list = [ {id:"name1 Surname1" , nb:120} ,
         {id:"name4 Surname4" , nb:120} ,
         {id:"name2", nb:632} , 
         {id:"name3Surname3", nb:102} , 
         {id:"surname4", nb:896} 
       ] 

我的搜索策略是“id”。 如您所见,我有不同的格式:

用空格分隔名字 - 姓氏,仅名称,仅姓氏。

我的目的是通过id(其名称或姓氏值)搜索成员。 我的结果应该是其IDS包含我的搜索值项目的项目,即使名称和姓氏反转:名称和姓氏的顺序可能会更改

例如:

  • 如果我搜索:“name1” - > 结果:name1 Surname1
  • 如果我搜索:“surname4 name4” - > 结果:id:“name4 Surname4”,nb:120
  • 如果我搜索:“name1 Surn” - > 结果:name1 Surname1
  • 如果我搜索:“Surn name1” - > 结果:name1 Surname1
  • 如果我搜索:“name1 SurAAA” - > 结果 :(没有)
  • 如果我搜索:“AAAA Surname1” - > 结果 :(没有)
  • 如果我搜索:“name1Surname1” - > 结果 :(没有)
  • 如果我搜索:“name” - > 结果:name1 Surname1,name2,name3Surname3,surname4

总结:

我应该搜索项目:

  • 对应我搜索的项目
  • 从我搜索的项目开始

我尝试过 RegExp 解决方案,如下所示:

findPhones(written) {
    this.splits = written.split(' ');
    if (this.splits[0] === "") // Case of empty string
    {
      return this.filteredPhones = [];
    }
    this.filteredResult = List.filter((item) => {
      const regex = new RegExp(written, 'gi');  // g : global & i: insentisive case
      return item.List.match(regex);
    }); 

但是这个解决方案很好,但它缺乏反转“姓氏”的条件,因为它可能会被反转:

例如:当我搜索“surname4 name4”时:我得到0结果;但实际上我应该把我列表中的第二个对象作为一个好结果:

{id:"name4 Surname4" , nb:120}

(似乎我应该结合两个过滤器操作)

有任何修复建议吗?

3 个答案:

答案 0 :(得分:0)

代码

选项1 - 正则表达式

注意:以下代码使用EscapeRegExp功能。此功能在this answer中找到。 JavaScript没有像其他语言那样拥有自己的正则表达式转义函数(例如Python)。您可以使用更好的方法,但我已将此代码用作实现的基础。如果愿意,您可以随时将该功能替换为另一种功能。

list = [
  {id: "name1 Surname1", nb: 120},
  {id: "name4 Surname4", nb: 120},
  {id: "name2", nb: 632},
  {id: "name3Surname3", nb: 102},
  {id: "surname4", nb: 896}
];

function Search(s) {
  var searches = s.value.split(" ").filter(String);
  var regex = GenerateRegExp(searches);
  console.log(regex);
  var matches = list.filter((i) => {
    const r = new RegExp(regex, 'gi');
    return r.test(i.id);
  });
  console.log(matches);
}

function GenerateRegExp(arr) {
  var s = "";
  arr.forEach(function(e) {
    s += "(?=.*" + EscapeRegExp(e) + ")";
  });
  return s += ".*";
}

function EscapeRegExp(str) {
  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
<input id=search type=search onkeyup="Search(this)" />

选项2 - 过滤器

此选项比上面的正则表达式选项更强大。

list = [
  {id: "name1 Surname1", nb: 120},
  {id: "name4 Surname4", nb: 120},
  {id: "name2", nb: 632},
  {id: "name3Surname3", nb: 102},
  {id: "surname4", nb: 896}
];

function Search(s) {
  var searches = s.value.split(" ").filter(String);
  console.log(all(searches, list));
}

function all(needles, haystacks) {
  return haystacks.filter((h) => {
    var string = h.id.toString().toLowerCase();
    var a = needles.filter((e) => {
      if (string.indexOf(e) !== -1) return e;
    });
    if (a.length === needles.length) return h;
  });
}
<input id=search type=search onkeyup="Search(this)" />

答案 1 :(得分:0)

以下应该做你需要的。它通过检查拆分输入中的每个术语来创建匹配数组,然后检查拆分输入数组长度是否与匹配数组长度相同

&#13;
&#13;
const list =[ {id:"name1 Surname1" , nb:120} ,
     {id:"name4 Surname4" , nb:120} ,
     {id:"name2", nb:632} , 
     {id:"name3Surname3", nb:102} , 
     {id:"surname4", nb:896} 
   ] 


const findPhones = function(written) {
  const splits = written.trim().toLowerCase().split(' ').filter(w => w);
  return list.filter(o => {
    const names = o.id.split(' ');
    const matches = splits.filter(w => names.some(s => s.toLowerCase().includes(w)))
    return names.length >= splits.length && splits.length === matches.length;
  });
}


const terms = [
  "name1", "surname4 name4", "name1 Surn", "Surn name1", "name1 SurAAA", "AAAA Surname1", "name1Surname1", "name"
];

terms.forEach(term=>{
  console.log('Term: ', term)
  console.log('Matches:', JSON.stringify(findPhones(term), null, ' '))
})
&#13;
.as-console-wrapper {top:0; max-height:none!important;height:100%;}
&#13;
&#13;
&#13;

答案 2 :(得分:0)

@charlietfl编写的代码使搜索不区分大小写,  当搜索的名字和姓氏不返回时,如果一个单词匹配第一个和最后一个(例如:搜索词surname4 name4不返回nb:896)

const list =[ {id:"name1 Surname1" , nb:120} ,
 {id:"name4 Surname4" , nb:120} ,
 {id:"name2", nb:632} , 
 {id:"name3Surname3", nb:102} , 
 {id:"surname4", nb:896} 
] 


const findPhones = function(written) {
    const splits = written.trim().toLowerCase().split(' ').filter(w => w);
    return list.filter(o => {
        const names = o.id.split(' ');
        const matches = splits.filter(w => names.some(s => s.toLowerCase().includes(w)))
        return names.length >= splits.length && splits.length === matches.length;
    });
}


const terms = [
  "name1", "surname4 name4", "name1 Surn", "Surn name1", "name1 SurAAA", "AAAA Surname1", "name1Surname1", "name"
];

terms.forEach(term=>{
  console.log('Term: ', term)
  console.log('Matches:', JSON.stringify(findPhones(term), null, ' '))
})