664

JavaScript で複数の区切り文字を使用して文字列を分割するにはどうすればよいですか?

コンマスペースの両方で分割しようとしていますが、AFAIK JavaScript のsplit()関数は 1 つのセパレーターしかサポートしていません。

4

25 に答える 25

891

パラメータとして正規表現を渡します。

js> "Hello awesome, world!".split(/[\s,]+/)
Hello,awesome,world!

追加するために編集:

配列の長さから 1 を引いたものを選択すると、最後の要素を取得できます。

>>> bits = "Hello awesome, world!".split(/[\s,]+/)
["Hello", "awesome", "world!"]
>>> bit = bits[bits.length - 1]
"world!"

...そして、パターンが一致しない場合:

>>> bits = "Hello awesome, world!".split(/foo/)
["Hello awesome, world!"]
>>> bits[bits.length - 1]
"Hello awesome, world!"
于 2009-03-16T11:30:45.590 に答える
265

JavaScript のsplit()メソッドに正規表現を渡すことができます。例えば:

"1,2 3".split(/,| /) 
["1", "2", "3"]

または、複数のセパレーターをまとめて 1 つのみとして機能させたい場合は、次のようにします。

"1, 2, , 3".split(/(?:,| )+/) 
["1", "2", "3"]

(非キャプチャ(?:)括弧を使用する必要があります。そうしないと、結果にスプライスされてしまうからです。または、Aaron のように賢く、文字クラスを使用することもできます。)

Safari と Firefox でテストされた例。

于 2009-03-16T11:29:36.343 に答える
89

別の単純だが効果的な方法は、分割と結合を繰り返し使用することです。

"a=b,c:d".split('=').join(',').split(':').join(',').split(',')

基本的に、分割の後に結合を行うことは、グローバル置換に似ているため、各セパレーターをコンマに置き換え、すべてが置換されると、コンマで最終的な分割を行います

上記の式の結果は次のとおりです。

['a', 'b', 'c', 'd']

これを拡張すると、関数に配置することもできます。

function splitMulti(str, tokens){
        var tempChar = tokens[0]; // We can use the first token as a temporary join character
        for(var i = 1; i < tokens.length; i++){
            str = str.split(tokens[i]).join(tempChar);
        }
        str = str.split(tempChar);
        return str;
}

使用法:

splitMulti('a=b,c:d', ['=', ',', ':']) // ["a", "b", "c", "d"]

この機能を頻繁に使用する場合は String.prototype.split、利便性のためにラッピングを検討する価値さえあるかもしれません (私の関数はかなり安全だと思います - 唯一の考慮事項は、条件の追加のオーバーヘッド (マイナー) と、制限引数の実装がないという事実です)配列が渡された場合)。

splitMulti以下にこのアプローチを使用して単純にラップする場合は、必ず関数を含めてください:)。また、ビルトインの拡張に眉をひそめる人がいることにも注意してください (多くの人が間違っており、競合が発生する可能性があるため)。疑いがある場合は、これを使用する前に上級者に相談するか、SO で質問してください:)

    var splitOrig = String.prototype.split; // Maintain a reference to inbuilt fn
    String.prototype.split = function (){
        if(arguments[0].length > 0){
            if(Object.prototype.toString.call(arguments[0]) == "[object Array]" ) { // Check if our separator is an array
                return splitMulti(this, arguments[0]);  // Call splitMulti
            }
        }
        return splitOrig.apply(this, arguments); // Call original split maintaining context
    };

使用法:

var a = "a=b,c:d";
    a.split(['=', ',', ':']); // ["a", "b", "c", "d"]

// Test to check that the built-in split still works (although our wrapper wouldn't work if it didn't as it depends on it :P)
        a.split('='); // ["a", "b,c:d"] 

楽しみ!

于 2016-05-02T06:39:45.640 に答える
29

簡単にしましょう: (RegEx に "[ ]+" を追加すると、"1 つ以上" を意味します)

これは、"+" と "{1,}" が同じであることを意味します。

var words = text.split(/[ .:;?!~,`"&|()<>{}\[\]\r\n/\\]+/); // note ' and - are kept
于 2015-08-31T22:27:01.633 に答える
8

分割関数をさらにカスタマイズしたい方のために、分割する文字のリストを使用して特定の文字列を分割する再帰アルゴリズムを作成しました。上記の投稿を見る前にこれを書きました。欲求不満のプログラマーの助けになることを願っています。

splitString = function(string, splitters) {
    var list = [string];
    for(var i=0, len=splitters.length; i<len; i++) {
        traverseList(list, splitters[i], 0);
    }
    return flatten(list);
}

traverseList = function(list, splitter, index) {
    if(list[index]) {
        if((list.constructor !== String) && (list[index].constructor === String))
            (list[index] != list[index].split(splitter)) ? list[index] = list[index].split(splitter) : null;
        (list[index].constructor === Array) ? traverseList(list[index], splitter, 0) : null;
        (list.constructor === Array) ? traverseList(list, splitter, index+1) : null;    
    }
}

flatten = function(arr) {
    return arr.reduce(function(acc, val) {
        return acc.concat(val.constructor === Array ? flatten(val) : val);
    },[]);
}

var stringToSplit = "people and_other/things";
var splitList = [" ", "_", "/"];
splitString(stringToSplit, splitList);

上記の例は次を返します。["people", "and", "other", "things"]

注:flatten関数はRosettaコードから取得されました

于 2012-08-27T15:23:41.603 に答える
8

セパレーターとして使用するすべての文字を単独またはまとめて正規表現にまとめて、分割関数に渡すことができます。たとえば、次のように書くことができます。

console.log( "dasdnk asd, (naks) :d skldma".split(/[ \(,\)]+/) );

出力は次のようになります。

["dasdnk", "asd", "naks", ":d", "skldma"]
于 2014-04-22T04:46:15.237 に答える
5

そのような関数の古典的な実装を提供します。このコードは、JavaScript のほぼすべてのバージョンで機能し、何らかの形で最適化されています。

  • 保守が難しい正規表現を使用していません
  • JavaScript の新機能は使用していません。
  • より多くのコンピューターメモリを必要とする複数の .split() .join() 呼び出しを使用しません

純粋なコード:

var text = "Create a function, that will return an array (of string), with the words inside the text";

println(getWords(text));

function getWords(text)
{
    let startWord = -1;
    let ar = [];

    for(let i = 0; i <= text.length; i++)
    {
        let c = i < text.length ? text[i] : " ";

        if (!isSeparator(c) && startWord < 0)
        {
            startWord = i;
        }

        if (isSeparator(c) && startWord >= 0)
        {
            let word = text.substring(startWord, i);
            ar.push(word);

            startWord = -1;
        }
    }

    return ar;
}

function isSeparator(c)
{
    var separators = [" ", "\t", "\n", "\r", ",", ";", ".", "!", "?", "(", ")"];
    return separators.includes(c);
}

プレイグラウンドで実行されているコードを確認できます: https://codeguppy.com/code.html?IJI0E4OGnkyTZnoszAzf

于 2019-09-07T15:02:10.343 に答える
2

これが必要な主な理由の 1 つは、 と の両方/でファイル パスを分割することです\。ちょっとトリッキーな正規表現なので、参考のためにここに投稿します。

var splitFilePath = filePath.split(/[\/\\]/);
于 2015-07-13T16:19:12.577 に答える
2

RegEx のパフォーマンスはわかりませんが、代わりに RegEx がネイティブの HashSet を活用し、O( max(str.length, delimeter.length) ) の複雑さで動作する別の方法を次に示します。

var multiSplit = function(str,delimiter){
    if (!(delimiter instanceof Array))
        return str.split(delimiter);
    if (!delimiter || delimiter.length == 0)
        return [str];
    var hashSet = new Set(delimiter);
    if (hashSet.has(""))
        return str.split("");
    var lastIndex = 0;
    var result = [];
    for(var i = 0;i<str.length;i++){
        if (hashSet.has(str[i])){
            result.push(str.substring(lastIndex,i));
            lastIndex = i+1;
        }
    }
    result.push(str.substring(lastIndex));
    return result;
}

multiSplit('1,2,3.4.5.6 7 8 9',[',','.',' ']);
// Output: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]

multiSplit('1,2,3.4.5.6 7 8 9',' ');
// Output: ["1,2,3.4.5.6", "7", "8", "9"]
于 2014-07-15T07:49:40.637 に答える
2

削除したいものではなく、残したいものを指定した方が簡単だと思います。

英単語だけを使いたい場合は、次のようなものを使用できます。

text.match(/[a-z'\-]+/gi);

例 (実行スニペット):

var R=[/[a-z'\-]+/gi,/[a-z'\-\s]+/gi];
var s=document.getElementById('s');
for(var i=0;i<R.length;i++)
 {
  var o=document.createElement('option');
  o.innerText=R[i]+'';
  o.value=i;
  s.appendChild(o);
 }
var t=document.getElementById('t');
var r=document.getElementById('r');

s.onchange=function()
 {
  r.innerHTML='';
  var x=s.value;
  if((x>=0)&&(x<R.length))
   x=t.value.match(R[x]);
  for(i=0;i<x.length;i++)
   {
    var li=document.createElement('li');
    li.innerText=x[i];
    r.appendChild(li);
   }
 }
<textarea id="t" style="width:70%;height:12em">even, test; spider-man

But saying o'er what I have said before:
My child is yet a stranger in the world;
She hath not seen the change of fourteen years,
Let two more summers wither in their pride,
Ere we may think her ripe to be a bride.

—Shakespeare, William. The Tragedy of Romeo and Juliet</textarea>

<p><select id="s">
 <option selected>Select a regular expression</option>
 <!-- option value="1">/[a-z'\-]+/gi</option>
 <option value="2">/[a-z'\-\s]+/gi</option -->
</select></p>
 <ol id="r" style="display:block;width:auto;border:1px inner;overflow:scroll;height:8em;max-height:10em;"></ol>
</div>

于 2015-08-25T13:25:38.790 に答える
2

引数の文字を使用して文字列を分割する C# string.Split() 関数の代わりを探しているときに、この質問に遭遇しました。

JavaScript では、 map と reduce を使用して同じことを行い、分割文字と中間値を反復処理できます。

let splitters = [",", ":", ";"]; // or ",:;".split("");
let start= "a,b;c:d";
let values = splitters.reduce((old, c) => old.map(v => v.split(c)).flat(), [start]);
// values is ["a", "b", "c", "d"]

flat() は中間結果を平坦化するために使用されるため、各反復はネストされた配列のない文字列のリストで機能します。各反復は、old のすべての値に分割を適用し、スプリッターの次の値で分割される中間結果のリストを返します。reduce() は、初期文字列値を含む配列で初期化されます。

于 2021-01-09T11:52:51.863 に答える
1

これをreduceとfilterで解決しました。それは最も読みやすい解決策や最速の解決策ではない可能性があり、実際にはおそらくAarons answere hereを使用するでしょうが、書くのは楽しかったです。

[' ','_','-','.',',',':','@'].reduce(
(segs, sep) => segs.reduce(
(out, seg) => out.concat(seg.split(sep)), []), 
['E-mail Address: user@domain.com, Phone Number: +1-800-555-0011']
).filter(x => x)

または関数として:

function msplit(str, seps) {
  return seps.reduce((segs, sep) => segs.reduce(
    (out, seg) => out.concat(seg.split(sep)), []
  ), [str]).filter(x => x);
}

これは出力されます:

['E','mail','Address','user','domain','com','0','Phone','Number','+1','800','555','0011']

最後にフィルターがないと、2 つの異なるセパレーターが隣り合っている配列に空の文字列が表示されます。

于 2020-09-18T20:52:43.403 に答える