javascript - 交叉文本以找到常用词

标签 javascript regex string text

我正在尝试找出哪一种是交叉一组文本并在其中找到常用词的最佳方式。鉴于这种情况:

var t1 = 'My name is Mary-Ann, and I come from Kansas!';
var t2 = 'John, meet Mary, she comes from far away';
var t3 = 'Hi Mary-Ann, come here, nice to meet you!';

交集结果应该是:

var result =["Mary"];

它应该能够忽略标点符号,如 .,!?-

使用正则表达式的解决方案是否是最优的?

最佳答案

这是一个经过测试的解决方案:

function intersect() {
   var set = {};
   [].forEach.call(arguments, function(a,i){
     var tokens = a.match(/\w+/g);
     if (!i) {
       tokens.forEach(function(t){ set[t]=1 });
     } else {
       for (var k in set){
         if (tokens.indexOf(k)<0) delete set[k];
       }
     }
   });
   return Object.keys(set);
}

这个函数是可变的,你可以用任意数量的文本调用它:

console.log(intersect(t1, t2, t3)) // -> ["Mary"] 

console.log(intersect(t1, t2)) // -> ["Mary", "from"] 

console.log(intersect()) // -> [] 

如果您需要支持非英语语言,那么这个正则表达式将不够用,因为 JavaScript 正则表达式对 Unicode 的支持很差。您要么使用 regex library或者您通过显式排除字符来定义正则表达式,如 a.match(/[^\s\-.,!?]+/g); (这对你来说可能就足够了)。


详细解释:

想法是用第一个文本的标记填充一个集合,然后从该集合中删除其他文本中缺少的标记。

  1. 集合是用作 map 的 JavaScript 对象。一些纯粹主义者会使用 Object.create(null)为了避免原型(prototype),我喜欢 {} 的简单性.
  2. 因为我希望我的函数是 variadic , 我用 arguments 而不是将传递的文本定义为显式参数。
  3. arguments不是一个真正的数组,所以要迭代它你需要一个 for循环或类似 [].forEach.call 的技巧.它起作用是因为 arguments"array-like" .
  4. 要标记化,我只需使用 match 匹配单词,这里没有什么特别的(不过请参阅上面关于更好地支持其他语言的注释)
  5. 我使用 !i检查它是否是第一个文本。在这种情况下,我只需将标记复制为集合中的属性。一定要用一个值,我用1 .以后,ES6 sets将使此处的意图更加明显。
  6. 对于以下文本,我遍历集合的元素(键)并删除不在标记数组 (tokens.indexOf(k)<0) 中的元素
  7. 最后,我返回集合的元素,因为我们需要一个数组。最简单的解决方案是使用 Object.keys .

关于javascript - 交叉文本以找到常用词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23905996/

相关文章:

c# - 搜索字符串模式

python - Python 中的正则表达式

java - 使用递归组合字符串

python - 为什么 str 不能得到第二个参数,而 __str__ 可以?

c# - 如何正确地将字符串传递给ffmpeg?

javascript - 检索到动态添加元素顶部的距离

javascript - 按顺序将项目添加到列表中

javascript - 如何在点击事件中设置全局变量?

Java正则表达式-用前导特殊字符分割字符串

javascript - FlatList renderItem 被多次调用