如何在JavaScript中使用多个分隔符拆分字符串?

如何在JavaScript中使用多个分隔符拆分字符串?

我试图在逗号空间上拆分,但AFAIK JavaScript的split()函数只支持一个分隔符。

771950 次浏览

您可以将正则表达式传递给JavaScript的split()方法。例如:

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

或者,如果您想允许多重分离器一起仅作为一个:

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

您必须使用非捕获(?:)括号,因为 否则它会被拼接回结果中或者你可以聪明点 像亚伦一样,使用字符类。

在Safari和Firefox中测试的示例。

传入一个regexp作为参数:

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

对于那些想要在拆分函数中进行更多自定义的人,我写了一个递归算法,它将给定的字符串与要拆分的字符列表拆分。我在看到上面的帖子之前写了这个。我希望它能帮助一些沮丧的程序员。

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函数取自罗塞塔密码

棘手的方法:

var s = "dasdnk asd, (naks) :d skldma";
var a = s.replace('(',' ').replace(')',' ').replace(',',' ').split(' ');
console.log(a);//["dasdnk", "asd", "naks", ":d", "skldma"]

你可以将所有要用作分隔符的字符单独或集体集中到正则表达式中,并将它们传递给拆分函数。例如,你可以写:

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

输出将是:

["dasdnk", "asd", "naks", ":d", "skldma"]

我不知道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"]

我使用regexp:

str =  'Write a program that extracts from a given text all palindromes, e.g. "ABBA", "lamal", "exe".';


var strNew = str.match(/\w+/g);


// Output: ["Write", "a", "program", "that", "extracts", "from", "a", "given", "text", "all", "palindromes", "e", "g", "ABBA", "lamal", "exe"]

我发现我需要这个的主要原因之一是在/\上拆分文件路径。这是一个有点棘手的正则表达式,所以我将在这里发布以供参考:

var splitFilePath = filePath.split(/[\/\\]/);

我认为它更容易如果你指定你想离开什么,而不是你想删除什么。

如果你只想要英语单词,你可以这样使用:

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>

让我们保持简单:(向RegEx添加 "[ ]+" 表示“1个或多个”)

这意味着“+”和“{1,}”是相同的。

var words = text.split(/[ .:;?!~,`"&|()<>{}\[\]\r\n/\\]+/); // note ' and - are kept

从@stephen-sweriduk解决方案开始(这对我来说更有趣!),我稍微修改了它以使其更通用和可重用:

/**
* Adapted from: http://stackoverflow.com/questions/650022/how-do-i-split-a-string-with-multiple-separators-in-javascript
*/
var StringUtils = {


/**
* Flatten a list of strings
* http://rosettacode.org/wiki/Flatten_a_list
*/
flatten : function(arr) {
var self=this;
return arr.reduce(function(acc, val) {
return acc.concat(val.constructor === Array ? self.flatten(val) : val);
},[]);
},


/**
* Recursively Traverse a list and apply a function to each item
* @param list array
* @param expression Expression to use in func
* @param func function of (item,expression) to apply expression to item
*
*/
traverseListFunc : function(list, expression, index, func) {
var self=this;
if(list[index]) {
if((list.constructor !== String) && (list[index].constructor === String))
(list[index] != func(list[index], expression)) ? list[index] = func(list[index], expression) : null;
(list[index].constructor === Array) ? self.traverseListFunc(list[index], expression, 0, func) : null;
(list.constructor === Array) ? self.traverseListFunc(list, expression, index+1, func) : null;
}
},


/**
* Recursively map function to string
* @param string
* @param expression Expression to apply to func
* @param function of (item, expressions[i])
*/
mapFuncToString : function(string, expressions, func) {
var self=this;
var list = [string];
for(var i=0, len=expressions.length; i<len; i++) {
self.traverseListFunc(list, expressions[i], 0, func);
}
return self.flatten(list);
},


/**
* Split a string
* @param splitters Array of characters to apply the split
*/
splitString : function(string, splitters) {
return this.mapFuncToString(string, splitters, function(item, expression) {
return item.split(expression);
})
},


}

然后

var stringToSplit = "people and_other/things";
var splitList = [" ", "_", "/"];
var splittedString=StringUtils.splitString(stringToSplit, splitList);
console.log(splitList, stringToSplit, splittedString);

作为原件回馈:

[ ' ', '_', '/' ] 'people and_other/things' [ 'people', 'and', 'other', 'things' ]

嗨,例如,如果您在String 07:05:45PM中拆分和替换

var hour = time.replace("PM", "").split(":");

结果

[ '07', '05', '45' ]

另一个简单但有效的方法是重复使用拆分+连接。

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

好好享受!

一个简单的方法是使用每个分隔符处理字符串的每个字符并构建一个拆分数组:

splix = function ()
{
u = [].slice.call(arguments); v = u.slice(1); u = u[0]; w = [u]; x = 0;


for (i = 0; i < u.length; ++i)
{
for (j = 0; j < v.length; ++j)
{
if (u.slice(i, i + v[j].length) == v[j])
{
y = w[x].split(v[j]); w[x] = y[0]; w[++x] = y[1];
};
};
};
  

return w;
};

console.logg = function ()
{
document.body.innerHTML += "<br>" + [].slice.call(arguments).join();
}


splix = function() {
u = [].slice.call(arguments);
v = u.slice(1);
u = u[0];
w = [u];
x = 0;
console.logg("Processing: <code>" + JSON.stringify(w) + "</code>");


for (i = 0; i < u.length; ++i) {
for (j = 0; j < v.length; ++j) {
console.logg("Processing: <code>[\x22" + u.slice(i, i + v[j].length) + "\x22, \x22" + v[j] + "\x22]</code>");
if (u.slice(i, i + v[j].length) == v[j]) {
y = w[x].split(v[j]);
w[x] = y[0];
w[++x] = y[1];
console.logg("Currently processed: " + JSON.stringify(w) + "\n");
};
};
};


console.logg("Return: <code>" + JSON.stringify(w) + "</code>");
};


setTimeout(function() {
console.clear();
splix("1.23--4", ".", "--");
}, 250);
@import url("http://fonts.googleapis.com/css?family=Roboto");


body {font: 20px Roboto;}

用法:splix(string, delimiters...)

示例:splix("1.23--4", ".", "--")

返回:["1", "23", "4"]

不是最好的方法,但可以使用多个和不同的分隔符/分隔符进行拆分

html

<button onclick="myFunction()">Split with Multiple and Different seperators/delimiters</button>
<p id="demo"></p>

javascript

<script>
function myFunction() {


var str = "How : are | you doing : today?";
var res = str.split(' | ');


var str2 = '';
var i;
for (i = 0; i < res.length; i++) {
str2 += res[i];
    

if (i != res.length-1) {
str2 += ",";
}
}
var res2 = str2.split(' : ');


//you can add countless options (with or without space)


document.getElementById("demo").innerHTML = res2;
}
</script>
a = "a=b,c:d"


array = ['=',',',':'];


for(i=0; i< array.length; i++){ a= a.split(array[i]).join(); }

这将返回不带特殊字符的字符串。

以下是在ES6中实现相同的新方法:

function SplitByString(source, splitBy) {
var splitter = splitBy.split('');
splitter.push([source]); //Push initial value


return splitter.reduceRight(function(accumulator, curValue) {
var k = [];
accumulator.forEach(v => k = [...k, ...v.split(curValue)]);
return k;
});
}


var source = "abc,def#hijk*lmn,opq#rst*uvw,xyz";
var splitBy = ",*#";
console.log(SplitByString(source, splitBy));

请在此功能中注意:

  • 没有Regex的参与
  • 以与source中出现的相同顺序返回拆分值

上述代码的结果将是:

在此处输入图片描述

我将为这样的函数提供一个经典的实现。该代码适用于几乎所有版本的JavaScript,并且在某种程度上是最佳的。

  • 它不使用regex,这很难维护
  • 它不使用JavaScript的新功能
  • 它不使用需要更多计算机内存的多个.分裂().加入()调用

纯代码:

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);
}

您可以在playground中看到运行的代码: https://codeguppy.com/code.html?IJI0E4OGnkyTZnoszAzf

我对@Brian答案的重构

var string = 'and this is some kind of information and another text and simple and some egample or red or text';
var separators = ['and', 'or'];


function splitMulti(str, separators){
var tempChar = 't3mp'; //prevent short text separator in split down
            

//split by regex e.g. \b(or|and)\b
var re = new RegExp('\\b(' + separators.join('|') + ')\\b' , "g");
str = str.replace(re, tempChar).split(tempChar);
            

// trim & remove empty
return str.map(el => el.trim()).filter(el => el.length > 0);
}


console.log(splitMulti(string, separators))

通过. com/. net/拆分URL

url.split(/\.com\/|\.net\//)

我用Reduce和Filter解决了这个问题。它可能不是最易读的解决方案,也不是最快的解决方案,在现实生活中我可能会使用Aarons回答说,但写起来很有趣。

[' ','_','-','.',',',':','@'].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']

如果最后没有过滤器,您将在数组中获得空字符串,其中两个不同的分隔符相邻。

我在寻找C#string. Split()函数的替代品时遇到了这个问题,该函数使用其参数中的字符拆分字符串。

在JavaScript中,您可以使用map an duce来迭代拆分字符和中间值:

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

用于展平中间结果,因此每次迭代都在没有嵌套数组的字符串列表上工作。每次迭代都将拆分应用于旧值中的所有值,然后返回要被拆分器中的下一个值拆分的中间结果列表。减少()用包含初始字符串值的数组初始化。

以下是使用Regex可能会有所帮助的一些案例:

  • \W匹配任何字符,否则单词字符[a-zA-Z0-9_]。例子:
("Hello World,I-am code").split(/\W+/); // would return [ 'Hello', 'World', 'I', 'am', 'code' ]
  • \s+匹配一个或多个空格
  • \d匹配一个数字
  • 如果你想用一些字符分割,让我们说,-,你可以使用str.split(/[,-]+/)…等

我很惊讶还没有人提出这个建议,但是我的hack-ey(和疯狂的快速)解决方案是在分裂同一个字符之前附加几个“替换”调用。

即去掉a、b、c、d和e:

let str = 'afgbfgcfgdfgefg'
let array = str.replace('a','d').replace('b','d').replace('c','d').replace('e','d').split('d')

这可以方便地推广到分裂器数组,如下所示:

function splitByMany( manyArgs, string ) {
do {
let arg = manyArgs.pop()
string = string.replace(arg, manyArgs[0])
} while (manyArgs.length > 2)
return string.split(manyArgs[0])
}

所以,在你的情况下,你可以打电话给

let array = splitByMany([" ", ","], 'My long string containing commas, and spaces, and more commas');

查看我的简单库github

如果您真的不想访问存储库或与之交互,以下是工作代码:

/**
*
* @param {type} input The string input to be split
* @param {type} includeTokensInOutput If true, the tokens are retained in the splitted output.
* @param {type} tokens The tokens to be employed in splitting the original string.
* @returns {Scanner}
*/
function Scanner(input, includeTokensInOutput, tokens) {
this.input = input;
this.includeTokensInOutput = includeTokensInOutput;
this.tokens = tokens;
}


Scanner.prototype.scan = function () {
var inp = this.input;


var parse = [];
this.tokens.sort(function (a, b) {
return b.length - a.length; //ASC, For Descending order use: b - a
});
for (var i = 0; i < inp.length; i++) {




for (var j = 0; j < this.tokens.length; j++) {


var token = this.tokens[j];
var len = token.length;
if (len > 0 && i + len <= inp.length) {
var portion = inp.substring(i, i + len);
if (portion === token) {
if (i !== 0) {//avoid empty spaces
parse[parse.length] = inp.substring(0, i);
}
if (this.includeTokensInOutput) {
parse[parse.length] = token;
}
inp = inp.substring(i + len);
i = -1;
break;
}


}


}


}
if (inp.length > 0) {
parse[parse.length] = inp;
}


return parse;




};

用法很简单:

    var tokens = new Scanner("ABC+DE-GHIJK+LMNOP", false , new Array('+','-')).scan();


console.log(tokens);

给予:

['ABC', 'DE', 'GHIJK', 'LMNOP']

如果您希望在输出中包含拆分令牌(+ and -),请将false设置为true,瞧!它仍然有效。

现在的用法是:

var tokens = new Scanner("ABC+DE-GHIJK+LMNOP", true , new Array('+','-')).scan();

console.log(tokens);

将提供:

['ABC', '+', 'DE', '-', 'GHIJK', '+', 'LMNOP']

享受吧!