仅在指定字符的第一个实例上拆分字符串

Ofe*_*all 237 javascript regex jquery

在我的代码中,我基于分割字符串_并获取数组中的第二项.

var element = $(this).attr('class');
var field = element.split('_')[1];
Run Code Online (Sandbox Code Playgroud)

需要good_luck并提供给我luck.效果很好!

但是,现在我有一个看起来像的课程good_luck_buddy.如何让我的javascript忽略第二个_并给我luck_buddy

var field = element.split(new char [] {'_'}, 2);在ac#stackoverflow中找到了这个答案,但它不起作用.我在jsFiddle试了一遍......

Mar*_*ark 363

使用捕获括号:

"good_luck_buddy".split(/_(.+)/)[1]
"luck_buddy"
Run Code Online (Sandbox Code Playgroud)

它们被定义为

如果separator包含捕获括号,则在数组中返回匹配的结果.

所以在这种情况下我们想要拆分_.+(即拆分分隔符是一个以字母开头的子字符串_),但也让结果包含我们分隔符的某些部分(即后面的所有内容_).

在此示例中,我们的分隔符(匹配_(.+))是_luck_buddy捕获的组(在分隔符内)lucky_buddy.没有捕获括号,luck_buddy(匹配.+)将不会包含在结果数组中,因为简单的情况split是分隔符不包含在结果中.

  • 任何人都知道为什么我得到一个额外的空字符串元素:in:`"纵横比:16:9".split(/ :(.+)/)`out:`["纵横比","16:9" ,""]` (27认同)
  • 您甚至不需要(?),只需使用/_(.+)/在第一个_之后再捕获1个字符 (21认同)
  • 需要明确的是,此解决方案的工作原因是因为第一个`_`之后的所有内容都在捕获组内匹配,并因此而被添加到令牌列表中. (12认同)
  • @katylavallee - 这可能会有所帮助:http://stackoverflow.com/questions/12836062/javascript-string-split-returns-an-array-with-two-elements-instead-of-one因为分隔符是"":16 :9"`,分隔符后面没有任何内容,因此在结尾处创建空字符串. (4认同)
  • 十分优雅.奇迹般有效.谢谢. (3认同)
  • @YanFoto 您可以使用 `/_([^]+)/` 特别是 `[^]` 来捕获包括换行符在内的所有字符 (3认同)
  • 不需要吗?并且您最好使用`/_(.*)/`(* 而不是+)来支持以_ 结尾的字符串 (2认同)
  • only in JavaScript 是使用额外的虚拟元素创建数组的最简单的解决方案 (2认同)

ken*_*bec 209

你需要什么正则表达式和数组?

myString = myString.substring(myString.indexOf('_')+1)
Run Code Online (Sandbox Code Playgroud)

var myString= "hello_there_how_are_you"
myString = myString.substring(myString.indexOf('_')+1)
console.log(myString)
Run Code Online (Sandbox Code Playgroud)

  • 答案输出字符串的第二部分.如果你想要第一部分怎么办?使用`var str ="good_luck_buddy",res = str.split(/_(.+)/);`你得到所有部分:`console.log(res [0]); 的console.log(RES [1]);` (9认同)
  • string!== String.javascript区分大小写. (5认同)
  • @PeterLeger let split = `[ string.substring(0, string.indexOf(options.divider)), string.substring(string.indexOf(options.divider) + 1) ]` 就这样了。还带有可变针的支持 (4认同)
  • 我认为这是最好的答案.也可以在第二个`_`之后通过写:`myString.substring(myString.indexOf('_',myString().indexOf('_')+ 1)+ 1)来获取字符串. (3认同)

yon*_*nas 31

我不惜一切代价避免使用RegExp.这是你可以做的另一件事:

"good_luck_buddy".split('_').slice(1).join('_')
Run Code Online (Sandbox Code Playgroud)

  • 一个害怕RegExp的人永远不会被告知RegExp是多么伟大.你需要自己找到门.一旦你在那里,你永远不会回头.几年后再问我一次,你会告诉我它有多棒. (14认同)
  • 哈!我在4年多前写过这篇评论.我现在肯定会加入RegExp!:) (11认同)
  • @yonas你最好不要。当**你需要它**时,RegExp很棒。不是这里的情况。检查更新的测试:https://jsperf.com/split-by-first-colon/2 (6认同)
  • @yonas拿红丸! (2认同)
  • @yonas是的,拿红丸!它会让你的生活更快,即使是短小的字符串:http://jsperf.com/split-by-first-colon (2认同)
  • 很好,这正是我想要做的。@bfontaine 关心计算机的执行效率,而真正重要的是其他开发人员理解它的效率,这就是应避免使用 RegExp 的原因。Christiaan Westerbeek 有一个很好的观点,即它在某些情况下可能很棒,但不同意不惜一切代价避免它。您给开发人员带来的痛苦通常超过了便利,但并非总是如此。 (2认同)

ont*_*rif 27

在解构赋值的帮助下,它可以更具可读性:

let [first, ...rest] = "good_luck_buddy".split('_')
rest = rest.join('_')
Run Code Online (Sandbox Code Playgroud)

  • ES6 的最佳答案 (3认同)

Dar*_*Lee 13

这个解决方案对我有用

var str = "good_luck_buddy";
var index = str.indexOf('_');
var arr = [str.slice(0, index), str.slice(index + 1)];

//arr[0] = "good"
//arr[1] = "luck_buddy"
Run Code Online (Sandbox Code Playgroud)

或者

var str = "good_luck_buddy";
var index = str.indexOf('_');
var [first, second] = [str.slice(0, index), str.slice(index + 1)];

//first = "good"
//second = "luck_buddy"
Run Code Online (Sandbox Code Playgroud)

  • 但是,如果分隔符超过 1 个字符,则此方法不起作用。 (2认同)

Kra*_*ken 13

Nowadays String.prototype.split does indeed allow you to limit the number of splits.

str.split([separator[, limit]])

...

limit Optional

限制拆分数量的非负整数。如果提供,则在每次出现指定分隔符时拆分字符串,但在数组中放置限制条目时停止。任何剩余的文本根本不包含在数组中。

如果在达到限制之前到达字符串的末尾,则数组包含的条目可能少于限制。如果 limit 为 0,则不执行拆分。

警告

它可能不会像您期望的那样工作。我希望它会忽略其余的分隔符,但是当它达到限制时,它会再次拆分剩余的字符串,从返回结果中省略拆分后的部分。

let str = 'A_B_C_D_E'
const limit_2 = str.split('_', 2)
limit_2
(2) ["A", "B"]
const limit_3 = str.split('_', 3)
limit_3
(3) ["A", "B", "C"]
Run Code Online (Sandbox Code Playgroud)

我希望:

let str = 'A_B_C_D_E'
const limit_2 = str.split('_', 2)
limit_2
(2) ["A", "B_C_D_E"]
const limit_3 = str.split('_', 3)
limit_3
(3) ["A", "B", "C_D_E"]

Run Code Online (Sandbox Code Playgroud)

  • 这也是 java String.split() 的工作原理。 (2认同)

seb*_*ace 11

用唯一的占位符替换第一个实例,然后从那里拆分.

"good_luck_buddy".replace(/\_/,'&').split('&')

["good","luck_buddy"]
Run Code Online (Sandbox Code Playgroud)

当需要拆分的两侧时,这更有用.

  • 这对字符串施加了不必要的约束。 (3认同)
  • @sebjwallace 无论您选择什么,都意味着您不能在字符串中包含该字符。例如,我认为“fish&chips_are_great”给出了 [fish,chips, are_great]。 (3认同)

小智 11

获取字符串中的第一个键和剩余部分的简单 ES6 方法是:

 const [key, ...rest] = "good_luck_buddy".split('_')
 const value = rest.join('_')
 console.log(key, value) // good, luck_buddy
Run Code Online (Sandbox Code Playgroud)


Édi*_*ças 9

我需要字符串的两个部分,因此,正则表达式后视可以帮助我解决这个问题。

const full_name = 'Maria do Bairro';
const [first_name, last_name] = full_name.split(/(?<=^[^ ]+) /);
console.log(first_name);
console.log(last_name);
Run Code Online (Sandbox Code Playgroud)


Cha*_*ert 8

非正则解决方案

我运行了一些基准测试,这个解决方案大获全胜:1

str.slice(str.indexOf(delim) + delim.length)

// as function
function gobbleStart(str, delim) {
    return str.slice(str.indexOf(delim) + delim.length);
}

// as polyfill
String.prototype.gobbleStart = function(delim) {
    return this.slice(this.indexOf(delim) + delim.length);
};
Run Code Online (Sandbox Code Playgroud)

与其他解决方案的性能比较

唯一的竞争者是同一行代码,除了使用substr代替slice.

我尝试过的涉及splitor RegExps 的其他解决方案对性能造成了很大的影响,并且速度慢了大约 2个数量级。当然,join在 的结果上使用split会增加额外的性能损失。

他们为什么慢?每当必须创建新对象或数组时,JS 都必须向操作系统请求一块内存。这个过程非常缓慢。

以下是一些一般准则,以防您追求基准:

  • 对象{}或数组的新动态内存分配[](如split创建的)将在性能上花费很多。
  • RegExp 搜索更复杂,因此比字符串搜索更慢。
  • 如果您已经有一个数组,那么解构数组的速度与显式索引它们的速度差不多,而且看起来很棒。

超越一审

这是一个解决方案,它将切片到并包括第 n 个实例。它不是那么快,但在 OP 的问题上,gobble(element, '_', 1)仍然比 a RegExporsplit解决方案快 2 倍以上,并且可以做更多:

/*
`gobble`, given a positive, non-zero `limit`, deletes
characters from the beginning of `haystack` until `needle` has
been encountered and deleted `limit` times or no more instances
of `needle` exist; then it returns what remains. If `limit` is
zero or negative, delete from the beginning only until `-(limit)`
occurrences or less of `needle` remain.
*/
function gobble(haystack, needle, limit = 0) {
  let remain = limit;
  if (limit <= 0) { // set remain to count of delim - num to leave
    let i = 0;
    while (i < haystack.length) {
      const found = haystack.indexOf(needle, i);
      if (found === -1) {
        break;
      }
      remain++;
      i = found + needle.length;
    }
  }

  let i = 0;
  while (remain > 0) {
    const found = haystack.indexOf(needle, i);
    if (found === -1) {
      break;
    }
    remain--;
    i = found + needle.length;
  }
  return haystack.slice(i);
}
Run Code Online (Sandbox Code Playgroud)

使用上面的定义,gobble('path/to/file.txt', '/')将给出文件的名称,并gobble('prefix_category_item', '_', 1)像本答案中的第一个解决方案一样删除前缀。


  1. 测试在 macOSX 10.14 上的 Chrome 70.0.3538.110 中运行。

  • 我同意。尽管微基准测试有点有趣,但您应该依靠编译器或翻译器进行优化。谁知道呢。Mb 读这篇文章的人正在构建一个编译器或使用 ejs/嵌入式并且不能使用正则表达式。但是,对于我的特定情况,这看起来比正则表达式更好。(我会删除“最快的解决方案”) (3认同)
  • 我毫不怀疑 JIT 编译器会有所帮助。然而,这些测试表明,使用简单的字符串函数仍然可以提高性能(并避免复杂、容易出错的正则表达式)。 (2认同)

Cha*_*ndu 7

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

var arr = element.split(/_(.*)/)
Run Code Online (Sandbox Code Playgroud) 您可以使用指定拆分限制的第二个参数.即:var field = element.split('_',1)[1];

  • 这仅指定返回多少拆分项,而不是指定拆分的次数.`'good_luck_buddy'.split('_',1);`只返回`['good']` (6认同)

Jam*_*s T 5

将 stringreplace()方法与regex结合使用:

var result = "good_luck_buddy".replace(/.*?_/, "");
console.log(result);
Run Code Online (Sandbox Code Playgroud)

此正则表达式匹配第一个__本身之前的 0 个或多个字符。然后匹配项将替换为空字符串。

  • `document.body` 依赖于 DOM 的存在,并且它不能在纯 JavaScript 环境中工作。`console.log` 足以达到此目的,或者只需将结果保留在变量中以供检查。 (2认同)