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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4607745/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 13:14:48  来源:igfitidea点击:

split string only on first instance of specified character

javascriptjqueryregex

提问by Ofeargall

In my code I split a string based on _and grab the second item in the array.

在我的代码中,我拆分了一个字符串_并抓取了数组中的第二个项目。

var element = $(this).attr('class');
var field = element.split('_')[1];

Takes good_luckand provides me with luck. Works great!

获取good_luck并提供给我luck。效果很好!

But, now I have a class that looks like good_luck_buddy. How do I get my javascript to ignore the second _and give me luck_buddy?

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

I found this var field = element.split(new char [] {'_'}, 2);in a c# stackoverflow answer but it doesn't work. I tried it over at jsFiddle...

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

回答by Mark

Use capturing parentheses:

使用捕获括号

"good_luck_buddy".split(/_(.+)/)[1]
"luck_buddy"

They are defined as

它们被定义为

If separatorcontains capturing parentheses, matched results are returned in the array.

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

So in this case we want to split at _.+(i.e. split separator being a sub string starting with _) but alsolet the result contain some part of our separator (i.e. everythingafter _).

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

In this example our separator (matching _(.+)) is _luck_buddyand the captured group (within the separator) is lucky_buddy. Without the capturing parenthesis the luck_buddy(matching .+) would've not been included in the result array as it is the case with simple splitthat separators are not included in the result.

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

回答by kennebec

What do you need regular expressions and arrays for?

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

myString = myString.substring(myString.indexOf('_')+1)

var myString= "hello_there_how_are_you"
myString = myString.substring(myString.indexOf('_')+1)
console.log(myString)

回答by yonas

I avoid RegExp at all costs. Here is another thing you can do:

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

"good_luck_buddy".split('_').slice(1).join('_')

回答by sebjwallace

Replace the first instance with a unique placeholder then split from there.

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

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

["good","luck_buddy"]

This is more useful when both sides of the split are needed.

当需要拆分的双方时,这更有用。

回答by Chandu

You can use the regular expression like:

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

var arr = element.split(/_(.*)/)
You can use the second parameter which specifies the limit of the split. i.e: var field = element.split('_', 1)[1]; 您可以使用第二个参数来指定拆分的限制。即:var field = element.split('_', 1)[1];

回答by Kraken

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

如今String.prototype.split确实允许您限制拆分的数量。

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

...

limit Optional

A non-negative integer limiting the number of splits. If provided, splits the string at each occurrence of the specified separator, but stops when limit entries have been placed in the array. Any leftover text is not included in the array at all.

The array may contain fewer entries than limit if the end of the string is reached before the limit is reached. If limit is 0, no splitting is performed.

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

...

限制可选

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

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

caveat

警告

It might not work the way you expect. I was hoping it would just ignore the rest of the delimiters, but instead, when it reaches the limit, it splits the remaining string again, omitting the part after the split from the return results.

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

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"]

I was hoping for:

我希望:

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"]

回答by Alex Vidal

Javascript's String.splitunfortunately has no way of limiting the actual number of splits. It has a second argument that specifies how many of the actual split items are returned, which isn't useful in your case. The solution would be to split the string, shift the first item off, then rejoin the remaining items::

String.split不幸的是,Javascript无法限制拆分的实际数量。它有第二个参数,用于指定返回的实际拆分项的数量,这在您的情况下没有用。解决方案是拆分字符串,将第一个项目移开,然后重新加入其余项目:

var element = $(this).attr('class');
var parts = element.split('_');

parts.shift(); // removes the first item from the array
var field = parts.join('_');

回答by Darren Lee

This solution worked for me

这个解决方案对我有用

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"

OR

或者

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"

回答by ont.rif

With help of destructuring assignment it can be more readable:

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

let [first, ...rest] = "good_luck_buddy".split('_')
rest = rest.join('_')

回答by Chaim Leib Halbert

Fastest solution?

最快的解决方案?

I ran some benchmarks, and this solution won hugely:1

我运行了一些基准测试,这个解决方案大获全胜: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);
};

Performance comparison with other solutions

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

The only close contender was the same line of code, except using substrinstead of slice.

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

Other solutions I tried involving splitor RegExps took a big performance hit and were about 2 orders of magnitudeslower. Using joinon the results of split, of course, adds an additional performance penalty.

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

Why are they slower? Any time a new object or array has to be created, JS has to request a chunk of memory from the OS. This process is very slow.

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

Here are some general guidelines, in case you are chasing benchmarks:

以下是一些通用指南,以防您追求基准:

  • New dynamic memory allocations for objects {}or arrays [](like the one that splitcreates) will cost a lot in performance.
  • RegExpsearches are more complicated and therefore slower than string searches.
  • If you already have an array, destructuring arrays is about as fast as explicitly indexing them, and looks awesome.
  • 对象{}或数组的新动态内存分配[](如split创建的)将在性能上花费很多。
  • RegExp搜索更复杂,因此比字符串搜索更慢。
  • 如果你已经有一个数组,解构数组的速度和显式索引它们一样快,而且看起来很棒。

Removing beyond the first instance

超越一审

Here's a solution that will slice up to and including the nth instance. It's not quite as fast, but on the OP's question, gobble(element, '_', 1)is still >2x faster than a RegExpor splitsolution and can do more:

这是一个解决方案,它将切片到并包括第 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);
}

With the above definition, gobble('path/to/file.txt', '/')would give the name of the file, and gobble('prefix_category_item', '_', 1)would remove the prefix like the first solution in this answer.

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



  1. Tests were run in Chrome 70.0.3538.110 on macOSX 10.14.
  1. 测试在 macOSX 10.14 上的 Chrome 70.0.3538.110 中运行。