web-dev-qa-db-ja.com

指定された文字の最初のインスタンスでのみ文字列を分割します

私のコードでは、_に基づいて文字列を分割し、配列の2番目の項目を取得しました。

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

good_luckを取り、私にluckを提供します。よく働く!

しかし、今、私はgood_luck_buddyのように見えるクラスを持っています。 2番目の_を無視してluck_buddyを教えてもらうにはどうすればよいですか。

私はc#stackoverflowの回答でこのvar field = element.split(new char [] {'_'}, 2);を見つけましたが、うまくいきません。私はjsFiddleでそれを試してみました...

215
Ofeargall

括弧を取り込む :を使ってください。

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

それらは次のように定義されます。

separatorにキャプチャ括弧が含まれている場合、一致した結果が配列に返されます。

したがって、この場合は_.+で分割します(つまり、分割区切り文字は_で始まるサブストリングです)だけでなく、も結果の一部を含めることができます。区切り文字(つまり、_の後のすべて)。

この例では、セパレータ(_(.+)と一致)は_luck_buddyで、キャプチャされたグループ(セパレータ内)はlucky_buddyです。括弧が括弧なしでは(luck_buddyと一致する).+は結果の配列に含まれていないでしょう。単純なsplitの場合のようにセパレータは結果に含まれないからです。

333
Mark F

正規表現と配列は何に必要ですか?

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

私はRegExpを絶対に避けます。これがあなたができるもう一つのことです:

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

最初のインスタンスを一意のプレースホルダーに置き換えて、そこから分割します。

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

["good","luck_buddy"]

分割の両側が必要なとき、これはより便利です。

10
sebjwallace

次のような正規表現を使うことができます。

var arr = element.split(/_(.*)/)
分割の制限を指定する2番目のパラメーターを使用できます。すなわち、var field = element.split( '_'、1)[1];
6
Chandu

JavascriptのString.splitには残念ながら実際の分割数を制限する方法はありません。実際の分割アイテムがいくつ返されるかを指定する2番目の引数がありますが、これはあなたの場合には役に立ちません。解決策は、文字列を分割し、最初の項目をシフトしてから、残りの項目を再結合することです。

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

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

最速の解決策は?

私はいくらか ベンチマーク を実行しました、そしてこの解決策は大いに勝ちました: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);
};

他のソリューションとのパフォーマンス比較

substrの代わりにsplitを使用することを除いて、唯一の近い競合者は同じコード行です。

私がsplitまたはRegExpsを使用して試した他の解決策は、パフォーマンスに大きな影響を及ぼし、2桁も遅くなりましたjoinの結果にsplitを使用すると、もちろんパフォーマンスがさらに低下します。

なぜ彼らは遅いのですか?新しいオブジェクトまたは配列を作成しなければならないときはいつでも、JSはOSからメモリの塊を要求しなければなりません。このプロセスはとても遅いです。

あなたがベンチマークを追いかけている場合に備えて、これはいくつかの一般的なガイドラインです:

  • オブジェクト{}または配列[]splitが作成するものなど)への新しい動的メモリ割り当ては、パフォーマンスが非常に高くなります。
  • RegExp検索は文字列検索よりも複雑で、したがって処理が遅くなります。
  • あなたが既に配列を持っているならば、配列を破壊することは明示的にそれらにインデックスを付けるのと同じくらい速く、そして素晴らしく見えます。

最初のインスタンスを超えて削除する

これは、n番目のインスタンスまでスライスしたものです。それほど速くはありませんが、OPの質問では、gobble(element, '_', 1)RegExpsplitのソリューションよりもまだ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);
}

上記の定義では、gobble('path/to/file.txt', '/')はファイルの名前を与え、gobble('prefix_category_item', '_', 1)はこの答えの最初の解決策のように接頭辞を取り除きます。


  1. テストはmacOSX 10.14上のChrome 70.0.3538.110で実行されました。
0

私は文字列の2つの部分が必要なので、後ろにある正規表現はこれを手助けしてくれます。

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

これがトリックをする1つのRegExpです。

'good_luck_buddy' . split(/^.*?_/)[1] 

最初に、それはマッチを '^'で始めから始めさせる。次に、 '_'以外の任意の数の文字、つまり最初の '_'より前のすべての文字と一致します。

「?」パターン全体を一致させる最小数の文字が「。*?」で一致することを意味します。それには '_'が後に続き、それが最後の文字としてマッチに含まれるからです。

したがって、このsplit()はそのような一致部分を「スプリッタ」として使用し、結果から削除します。そのため、最初の '_'までのすべてが削除され、残りは結果の2番目の要素として表示されます。最初の要素は ""マッチした部分の前の部分を表します。マッチは最初から始まるので ""です。

以前の回答でChanduによって与えられた/_(.*)/のように機能する他の正規表現もあります。

/^.*?_/には、キャプチャグループがreplace()で果たす特別な役割を知らなくても、その機能を理解できるという利点があります。

0
Panu Logic

文字列 replace() メソッドを regex とともに使用します。

var result = "good_luck_buddy".replace(/.*?_/, "");
console.log(result);

この正規表現は、最初の_の前の0文字以上、および_そのものと一致します。一致は空の文字列に置き換えられます。

0
James T

これはChrome + FFで私のために働きました:

"foo=bar=beer".split(/^[^=]+=/)[1] // "bar=beer"
"foo==".split(/^[^=]+=/)[1] // "="
"foo=".split(/^[^=]+=/)[1] // ""
"foo".split(/^[^=]+=/)[1] // undefined

キーも必要な場合はこれを試してください。

"foo=bar=beer".split(/^([^=]+)=/) // Array [ "", "foo", "bar=beer" ]
"foo==".split(/^([^=]+)=/) // [ "", "foo", "=" ]
"foo=".split(/^([^=]+)=/) // [ "", "foo", "" ]
"foo".split(/^([^=]+)=/) // [ "foo" ]

//[0] = ignored (holds the string when there's no =, empty otherwise)
//[1] = hold the key (if any)
//[2] = hold the value (if any)
0
oriadam

正規表現に慣れていない私のような初心者にとって、この回避策はうまくいきました。

   var field = "Good_Luck_Buddy";
   var newString = field.slice( field.indexOf("_")+1 );

slice()メソッドは文字列の一部を抽出して新しい文字列を返し、indexOf()メソッドは文字列内で指定された値が最初に見つかった位置を返します。

0

Mark Fの解決策は素晴らしいですが、古いブラウザではサポートされていません。 Kennebecのソリューションは素晴らしいし、古いブラウザでもサポートされていますが、正規表現はサポートしていません。

だから、あなたが一度だけあなたの文字列を分割する解決策を探しているなら、それは古いブラウザによってサポートされていて、正規表現をサポートしている、これが私の解決策である:

String.prototype.splitOnce = function(regex)
{
    var match = this.match(regex);
    if(match)
    {
        var match_i = this.indexOf(match[0]);
        
        return [this.substring(0, match_i),
        this.substring(match_i + match[0].length)];
    }
    else
    { return [this, ""]; }
}

var str = "something/////another thing///again";

alert(str.splitOnce(/\/+/)[1]);
0
pmrotule