【问题标题】:Split string into array without deleting delimiter?将字符串拆分为数组而不删除分隔符?
【发布时间】:2014-07-01 06:36:11
【问题描述】:

我有一个类似的字符串

 "asdf a  b c2 "

我想把它拆分成这样的数组:

["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]

使用string.split(" ") 删除空格,结果如下:

["asdf", "a", "", "b", "c2"]

我想过插入额外的分隔符,例如

string.replace(/ /g, "| |").replace(/||/g, "|").split("|");

但这会产生意想不到的结果。

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    与其拆分,不如将其视为提取包含分隔符或 不是 分隔符的连续字符的字符串:

    'asdf a  b c2 '.match(/\S+|\s/g)
    // result: ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]
    'asdf a  b. . c2% * '.match(/\S+|\s/g)
    // result: ["asdf", " ", "a", " ", " ", "b.", " ", ".", " ", "c2%", " ", "*", " "]
    

    对比赛的更莎士比亚式的定义是:

    'asdf a  b c2 '.match(/ |[^ ]+/g)
    

    或(不致)+。

    【讨论】:

    • @Jack 我没有,但这似乎有效!显然,我需要学习正则表达式.. \S+ 是什么意思?
    • @gandalf3 \S\s 的反义词。也可以写成[^\s]
    • +1 但请注意:不需要将其包装在非捕获组 ((?: )) 中。 'asdf a b c2 '.match(/\S+|\s/g) 是一样的
    【解决方案2】:

    使用积极的前瞻:

    "asdf a  b c2 ".split(/(?= )/)
    // => ["asdf", " a", " ", " b", " c2", " "]
    

    后期编辑编辑: 正如我在 cmets 中所说,缺乏后视功能使这有点棘手。如果所有单词仅由字母组成,您可以使用\b 单词边界匹配器来假装lookbehind:

    "asdf a  b c2 ".split(/(?= )|\b/)
    // => ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]
    

    但是一旦你输入一些标点符号,它就会崩溃,因为它不仅会在空格上中断:

    "asdf-eif.b".split(/(?= )|\b/)
    // => ["asdf", "-", "eif", ".", "b"]
    

    如果您确实有不想中断的非字母,那么我也会建议一种后处理方法。

    Post-think EDIT:这是基于 JamesA 的原始想法,但改进为不使用 jQuery,并正确拆分:

    function chop(str) {
      var result = [];
      var pastFirst = false;
      str.split(' ').forEach(function(x) {
        if (pastFirst) result.push(' ');
        if (x.length) result.push(x);
        pastFirst = true;
      });
      return result;
    }
    chop("asdf a  b c2 ")
    // => ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]
    

    【讨论】:

    • 这非常适合我在问题中写的内容,但我刚刚意识到我在示例中犯了一个错误。请参阅我编辑的问题。
    • @gandalf3 你不希望它们作为字符串?
    • @limelights 我希望每个空间都在一个元素中。一个元素中不应该有空格 + 其他任何东西。
    • @limelights:原来分割是在每个空格之前;现在是每个空格之前和之后。不幸的是,JavaScript 没有lookbehind,所以这有点困难......
    • 谢谢!这很好用,但接受了杰克的回答,因为它更短(尽管该解决方案确实会拆分任何空白字符,而不仅仅是空格。但这对我来说很好)。如果可以的话,我会接受这两者.. (+1 btw)
    【解决方案3】:

    我很惊讶还没有人提到这一点,但为了完整起见,我会在这里发布。如果您的表达式中有捕获组,则.split 会将捕获的子字符串作为单独的条目包含在结果数组中:

    "asdf a  b c2 ".split(/( )/)  // or /(\s)/
    // ["asdf", " ", "a", " ", "", " ", "b", " ", "c2", " ", ""]
    

    注意,这与您指定的所需输出完全不同,因为它在两个连续空格之间和最后一个空格之后包含一个空字符串。

    如有必要,您可以像这样从结果数组中过滤掉所有空字符串:

    "asdf a  b c2 ".split(/( )/).filter(String)
    // ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]
    

    但是,如果这是您正在寻找的内容,我可能会建议您使用 @Jack's solution

    【讨论】:

    • 哎呀,对不起.. 最后的空字符串是错字。我已经编辑了我的问题。
    • @gandalf3 好的,我已经提供了一个替代解决方案,可以在这种情况下为您提供所需的结果。
    【解决方案4】:

    试试clean-split:

    const cleanSplit = require("clean-split");
    
    cleanSplit("a-b-c", "-");
    //=> ["a", "-", "b", "-", "c"]
    
    cleanSplit("a-b-c", "-", { anchor: "before" });
    //=> ["a-", "b-", "c"]
    
    cleanSplit("a-b-c", "-", { anchor: "after" });
    //=> ["a", "-b", "-c"]
    

    在底层,它使用的逻辑改编自:

    在你的情况下,你可以这样做:

    const cleanSplit = require("clean-split");
    
    cleanSplit("asdf a  b c2 ", " ");
    //=> ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]
    

    【讨论】:

      【解决方案5】:

      你可以使用一点 jQuery

      var toSplit = "asdf a  b c2 ".split(" ");
      $.each(toSplit, 
          function(index, value) { 
              if (toSplit[index] == '') { toSplit[index] = ' '} 
          }
      );
      

      这将创建您正在寻找的输出,而其他元素上没有前导空格。

      【讨论】:

      • 在较新的环境中不需要 jQuery - jQuery.each 是一个穷人的 [].foreach
      猜你喜欢
      • 2020-10-14
      • 2021-12-07
      • 2023-04-08
      • 2016-11-14
      • 2019-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多