【问题标题】:Lodash - Search if String contains a word that start withLodash - 搜索字符串是否包含以开头的单词
【发布时间】:2019-10-11 18:56:13
【问题描述】:

我有一个元素数组(比如说健身训练列表)。

我有一个搜索栏,我想创建一个搜索功能来查找特定培训

我知道如何将数组过滤为:

  1. 保持名称以在搜索栏中输入的字符串

    开头的训练
    array = array.filter(function(item) {
       return item.name.toLowerCase().startsWith(searchFilter.toLowerCase());
    });
    

示例:搜索 = "El"...

结果 -> ["Elizabeth", "Elisa"]

未获取结果 -> ["Open Elios"]

  1. 名称包含在搜索栏中输入的字符串

    的地方继续训练
    array = _.filter(array, function(item) {
       return _.includes(item.name.toLowerCase(), searchFilter.toLowerCase());
    });
    

示例:搜索 = "El"...

结果 -> ["Elizabeth", "Open Elios", "Camel"]

但这不是我想要的:

  1. 继续训练 name 包含以 在搜索栏中输入的字符串开头的单词

示例:搜索 = "El"...

结果 -> ["Elizabeth", "Open Elios"]

未获取结果 -> ["Camel"]

【问题讨论】:

  • 第一个和第三个有什么区别?
  • @adiga first: 1st = 如果字符串包含多个单词,则搜索只关注第一个单词。 3rd = 如果一个字符串包含多个单词,则搜索所关注的所有单词
  • @KevinB 你希望像hello-el 这样的值包含在过滤结果中吗?
  • 不是特别好,只有空间大
  • @CodeManiac 虽然不是很清楚,但我认为 OP 希望他提到name contains words starting with string typed in the search bar

标签: javascript arrays search filter lodash


【解决方案1】:

您可以为此使用正则表达式,例如:

const result = ["Elizabeth", "Open Elios", "Camel"].filter(v => /\bel/i.test(v));
console.log(result);

重要的部分是\b,意思是单词边界,基本上这个表达式/bel是在测试值是否包含以单词边界开头并被el休息的东西。

这是一个从字符串构造正则表达式的完整示例:

const array = ["Elizabeth", "Open Elios", "Camel"];
const searchFilter = 'El';
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

const result = array.filter(value => new RegExp(`\\b${escapeRegExp(searchFilter)}`, "i").test(value));

console.log(result);

【讨论】:

  • 这里唯一的问题是它也会捕获连字符的单词 Open-elio 也会被这个正则表达式捕获。不一定是好事或坏事,这取决于您想要的行为。
  • @CalIrvine 不仅连字符任何非单词字符都将匹配,例如 hello@el 或任何不是 digit, alphabet or _ 的字符,但这完全基于 OP 的要求
【解决方案2】:

您可以使用 RegExp 构造函数创建具有单词边界 \b 的动态正则表达式

function filter(arr, word) {
  const regex = new RegExp(`\\b${word}`, 'i');
  return arr.filter(n => regex.test(n))
}

console.log(filter(["Elizabeth", "Elisa", "Open Elios", "Camel"], "El"))

【讨论】:

  • 我认为使用\b 并不安全,因为它也会匹配hello-el 之类的值,尽管我不确定OP 是否想要它
【解决方案3】:

除了正则表达式,您还可以应用filter 两次,最后一次返回布尔值,用于包含当前字符串的过滤器。

var search_string = 'eli';
search_string = search_string.toLowerCase();
const arr = ["Elizabeth", "Open Elios", "Camel"];
const result = arr.filter(value => value.split(' ').filter(token => token.toLowerCase().startsWith(search_string)).length > 0);
console.log(result);

更新:

正如@Titus 在 cmets 中所建议的那样,您还可以使用 some() 方法过滤数据,如果找到以您的搜索字符串开头的标记,它将立即返回 true,而不是在过滤器中收集所有标记从您的搜索字符串开始。

var search_string = 'eli';
search_string = search_string.toLowerCase();
const arr = ["Elizabeth", "Open Elios", "Camel"];
const result = arr.filter(value => value.split(' ').some(token => token.toLowerCase().startsWith(search_string)));
console.log(result);

【讨论】:

  • 第二次,您可以使用.some(...) 代替.filter(....),这样您就不必检查所有单词或检查结果的长度。
  • 我刚刚意识到当字符串中有空格时它不起作用:/ ...例如,如果我写“Open E”,我得到了 0 结果
  • @KevinB 你能告诉我更多关于Open E 的信息吗?搜索值是多少?您拥有的词组是什么?
【解决方案4】:

您可以使用正则表达式来构建基于值的动态模式

(?:^|[ ])${value}
  • (?:^|[ ]) - 匹配字符串或空格的开头
  • ${value} - 来自搜索栏的动态值

let search = (value) => {
  const reg = `(?:^|[ ])${value}`
  const regex = new RegExp(reg,'gi')
  const result = ["Elizabeth", "Open Elios", "Camel"].filter(v => regex.test(v));
  return result
}

console.log(search('el'));

【讨论】:

    猜你喜欢
    • 2016-12-05
    • 2019-11-03
    • 1970-01-01
    • 1970-01-01
    • 2014-01-25
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多