拆分字符串并确保结果数组中没有重复项的最有效方法是什么?

时间:2013-12-29 22:15:36

标签: javascript regex arrays

我将javscript字符串拆分为一个数组,其元素只包含西里尔字符序列。

    var text = "где по его проекту был реализован первый в мире компьютер с хранимой в памяти программой — ACE."
    text=text.toLowerCase();
    var re = /[^йцукенгшщзхъёэждлорпавыфячсмитьбю]+/;
    words = text.split(re);

在上面的代码段中,单词将包含以下内容

["где", "по", "его", "проекту", "был", "реализован", "первый", "в", "мире", "компьютер", "с", "хранимой", "в", "памяти", "программой", ""] 

我需要从数组中删除副本。也就是说,我应该只看到“в”一次出现。我知道我可以在拆分后通过阵列执行此操作但不确定什么是最好的方法。是否可以使用拆分正则表达式执行此操作?

乔纳森

6 个答案:

答案 0 :(得分:7)

不是最有效的,但它干净而简单。

text.split(re).filter(function(str, idx, txtArray) {
    return txtArray.indexOf(str) === idx; 
});

基本上,如果找到的第一个索引与迭代中的当前索引不匹配,则它是重复的。

答案 1 :(得分:4)

你必须通过阵列。您可以记住在将对象用作地图之前是否已经看过该字符串的实例,例如:

var a = /* ...get the array... */;
var unique = [];
var n, len;
var str;
var seen = {};
for (n = 0, len = a.length; n < len; ++n) {
    str = a[n];
    if (!seen[str]) {
        seen[str] = true;
        unique.push(str);
    }
}

如果其中一个字符串值可能是对象上已存在的名称("toString""valueOf""hasOwnProperty"等),则必须修改if (!seen[str])检查使用hasOwnProperty代替:

if (!seen.hasOwnProperty(str)) {

...但如果字符串如您所示,则不需要。另一种方法是使用像“xx”这样的前缀:

var keystr = "xx" + str;
if (!seen[keystr]) {
    seen[keystr] = true;
    // ...
}

由于原始对象上没有以"xx"开头的对象属性,因此几乎肯定不会。


你在评论中说过:

  

我认为通过高效我的意思是最优雅的惯用javascript方式来做到这一点。

有趣的是,这不是我用过的定义。 :-)好的,这是使用ES5 filter的另一种方法,这肯定更像是JavaScript-y:

var a = /* ...get the array... */;
var seen = {};
a = a.filter(function(str) {
    if (!seen[str]) {
        seen[str] = true;
        return true;
    }
    return false;
});

答案 2 :(得分:2)

如果您愿意使用第三方库,我建议您查看Underscore。此库提供了uniq方法,您可以按以下方式应用该方法:

words = _.uniq(text.split(re));

答案 3 :(得分:0)

您可以使用其他一些内置函数获得.indexOf解决方案的“漂亮”:

var uniq = Object.keys(text.split(re).reduce(function(words, word) {
  words[word] = null;
  return words;
}, {}));

这只适用于较新版本的JavaScript(即不是旧版本的IE)。与Crowder先生的版本一样,这具有不是 O(n 2 算法的优点。在没有很多重复项的相当大的字符串上(例如,一个文本的页面),那些.indexOf()调用将开始为客户端CPU预热。

请注意,这将为您提供无特定顺序的独特单词。

答案 4 :(得分:0)

如何在正则表达式中使用负向前瞻,并使用.match方法返回匹配数组。

([йцукенгшщзхъёэждлорпавыфячсмитьбю]+)(?!.*\1)

答案 5 :(得分:0)

你可以这样做(分割器:" "):

var m = 'azerty rty aze rty aze'
    .replace(/(^| )([^ ]+)(?= |$)(?=.* \2( |$))/g, '') // removes duplicates
    .match(/[^ ]+/g) 
m; // ["azerty", "rty", "aze"]

当然不是最有效的方式。