JS拆分字符串和每个拆分的返回索引

时间:2019-07-31 16:25:52

标签: javascript regex split

我想在某个正则表达式上拆分文本,还希望在原始字符串中有一个拆分位置的索引。 在一个简单的例子中:

"bla blabla haha".splitOnRegexWithIndex(whitespaceRegex)

所需的输出是

[["bla", 0], ["blabla", 4], ["haha", 11]]

这里的正则表达式可以是任何东西,而不仅仅是空格,因此分隔符不是固定大小。

在正则表达式上进行分割。我不想使用indexOf在起始字符串中找到"blabla",因为那样的复杂度为O(n 2 ),在我的方案中是不可接受的。

6 个答案:

答案 0 :(得分:4)

您可以使用exec来检索具有索引的插入器:

const s = "bla blabla haha";

for (let m, reg = /\S+/g; m = reg.exec(s);) {
  console.log(m[0], m.index);
}

答案 1 :(得分:3)

您可以使用replace及其回叫

let str = `bla blabla haha`
let data = []

str.replace(/\S+/g,(m,offset)=>{
  data.push([m,offset])
})

console.log(data)

答案 2 :(得分:3)

这是基于.exec的可能实现:

function split_with_offset(str, re) {
    if (!re.global) {
        throw "no no no no :(";
    }
    let results = [];
    let m, p;
    while (p = re.lastIndex, m = re.exec(str)) {
        results.push([str.substring(p, m.index), p]);
    }
    results.push([str.substring(p), p]);
    return results;
}

console.log(split_with_offset("bla blabla haha", /\s+/g));
console.log(split_with_offset("   ", /\s+/g));
console.log(split_with_offset("", /\s+/g));

注意:正则表达式必须设置g标志。

答案 3 :(得分:3)

好吧,您可以先在正则表达式中使用String.split(),然后在结果数组上使用Array.map()。像这样:

function splitOnRegexWithIndex(str, regexp)
{
    let offset = 0, tmp;

    return str
        .split(regexp)
        .map(s => (tmp = offset, offset += s.length + 1, [s, tmp]));
}

console.log(
  JSON.stringify(splitOnRegexWithIndex("bla blabla haha", /\s/))
);
console.log(
  JSON.stringify(splitOnRegexWithIndex("bla blabla haha", /b/))
);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

但是,与警告一样,您应该注意,只有在拆分令牌的字符长度为1时,前一种方法才能很好地工作。但是,如果我们在拆分正则表达式上使用capturing groups,然后在结果数组上使用Array.reduce(),如下所示,就可以推广这种想法。

function splitOnRegexWithIndex(str, regexp)
{
    let offset = 0;

    // Add capturing group to the regular expression.
    regexp = new RegExp("(" + regexp.source + ")");

    // Split the string using capturing group and reduce
    // the resulting array.
    return str.split(regexp).reduce((acc, s, idx) =>
    {
        if (idx % 2 === 0)
            acc.push([s, offset]);

        offset += s.length;
        return acc;
    }, []);
}

console.log(
  JSON.stringify(splitOnRegexWithIndex("bla   blabla  haha", /\s+/))
);
console.log(
  JSON.stringify(splitOnRegexWithIndex("abaaagbacccbaaddytbax", /ba+/))
);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

答案 4 :(得分:1)

如果您的正则表达式不是全局的,则会得到两个部分,第一个匹配之前的一个,第二个匹配之后的一个。

gsub(pattern = "PCP", replacement = "", x = x) 

答案 5 :(得分:-1)

您可以使用mapindexOf来了解原始字符串中的位置:

 String.prototype.splitOnRegexWithIndex = function(regex){
    var splitted = this.split(regex);
    var original = this;

    return splitted.map(function(){
               return [this, original.indexOf(this)];
           });
}