Como faço para dividir uma string com vários separadores em JavaScript? Estou tentando dividir vírgulas e espaços, mas, AFAIK, a função de divisão do JS suporta apenas um separador.
Como faço para dividir uma string com vários separadores em JavaScript? Estou tentando dividir vírgulas e espaços, mas, AFAIK, a função de divisão do JS suporta apenas um separador.
Respostas:
Passe uma regexp como o parâmetro:
js> "Hello awesome, world!".split(/[\s,]+/)
Hello,awesome,world!
Editado para adicionar:
Você pode obter o último elemento selecionando o comprimento da matriz menos 1:
>>> bits = "Hello awesome, world!".split(/[\s,]+/)
["Hello", "awesome", "world!"]
>>> bit = bits[bits.length - 1]
"world!"
... e se o padrão não corresponder:
>>> bits = "Hello awesome, world!".split(/foo/)
["Hello awesome, world!"]
>>> bits[bits.length - 1]
"Hello awesome, world!"
(hello world)|\|
quais ainda não funcionaram. Alguma ideia?
Você pode passar uma regex para o operador de divisão do Javascript . Por exemplo:
"1,2 3".split(/,| /)
["1", "2", "3"]
Ou, se você deseja permitir que vários separadores juntos atuem como um só:
"1, 2, , 3".split(/(?:,| )+/)
["1", "2", "3"]
(Você precisa usar o não-capturante (? :) parens porque, caso contrário, ele será reposto no resultado. Ou você pode ser inteligente como Aaron e usar uma classe de personagem.)
(Exemplos testados no Safari + FF)
|
como mostra Jesse.
Outro método simples, porém eficaz, é usar split + join repetidamente.
"a=b,c:d".split('=').join(',').split(':').join(',').split(',')
Essencialmente, fazer uma divisão seguida por uma junção é como uma substituição global; portanto, isso substitui cada separador por vírgula; depois que todos são substituídos, ele faz uma divisão final por vírgula
O resultado da expressão acima é:
['a', 'b', 'c', 'd']
Expandindo isso, você também pode colocá-lo em uma função:
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;
}
Uso:
splitMulti('a=b,c:d', ['=', ',', ':']) // ["a", "b", "c", "d"]
Se você usa muito essa funcionalidade, pode até valer a pena considerar o agrupamento String.prototype.split
por conveniência (acho que minha função é razoavelmente segura - a única consideração é a sobrecarga adicional dos condicionais (secundários) e o fato de não haver uma implementação do argumento limite se uma matriz for passada).
Certifique-se de incluir a splitMulti
função se usar esta abordagem para a abaixo simplesmente a envolve :). Também vale a pena notar que algumas pessoas desaprovam a extensão de built-ins (como muitas pessoas fazem errado e podem ocorrer conflitos); portanto, em caso de dúvida, fale com alguém mais experiente antes de usar isso ou pergunte no 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
};
Uso:
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"]
Aproveitar!
for(var i = 0; i < tokens.length; i++)
e não for(var i = 1; i < tokens.length; i++)
?
tokens[1]
a salvar uma iteração tokens[0] == tempchar
e dividimos tempchar
após a iteração tokens
para concluir. Vou atualizar a resposta de acordo, obrigado @tic :).
Vamos simplificar: (adicione um "[] +" ao seu RegEx significa "1 ou mais")
Isso significa que "+" e "{1,}" são iguais.
var words = text.split(/[ .:;?!~,`"&|()<>{}\[\]\r\n/\\]+/); // note ' and - are kept
Método complicado:
var s = "dasdnk asd, (naks) :d skldma";
var a = s.replace('(',' ').replace(')',' ').replace(',',' ').split(' ');
console.log(a);//["dasdnk", "asd", "naks", ":d", "skldma"]
'('
para /(/g
substituir todos os (
elementos - g
é o mundial da bandeira para RegExp - por isso procurar todas as ocorrências de (
não primeiro
Para aqueles que desejam mais personalização em sua função de divisão, escrevi um algoritmo recursivo que divide uma determinada string com uma lista de caracteres para dividir. Eu escrevi isso antes de ver o post acima. Espero que ajude alguns programadores frustrados.
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);
O exemplo acima retorna: ["people", "and", "other", "things"]
Nota: a flatten
função foi retirada do Código Rosetta
Você pode agrupar todos os caracteres que deseja usar como separadores, singular ou coletivamente, em uma expressão regular e passá-los para a função de divisão. Por exemplo, você pode escrever:
console.log( "dasdnk asd, (naks) :d skldma".split(/[ \(,\)]+/) );
E a saída será:
["dasdnk", "asd", "naks", ":d", "skldma"]
Oi, por exemplo, se você dividiu e substituiu na String 07:05:45 PM
var hour = time.replace("PM", "").split(":");
Resultado
[ '07', '05', '45' ]
Aqui está uma nova maneira de obter o mesmo no 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));
Observe nesta função:
source
O resultado do código acima seria:
a = "a=b,c:d"
array = ['=',',',':'];
for(i=0; i< array.length; i++){ a= a.split(array[i]).join(); }
isso retornará a string sem um caractere especial.
Minha refatoração da resposta @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))
Acho que uma das principais razões pelas quais eu preciso disso é dividir os caminhos de arquivo em ambos /
e \
. É um pouco de regex complicado, por isso vou publicá-lo aqui para referência:
var splitFilePath = filePath.split(/[\/\\]/);
Eu acho que é mais fácil se você especificar o que deseja sair, em vez do que deseja remover.
Como se você quiser ter apenas palavras em inglês, pode usar algo como isto:
text.match(/[a-z'\-]+/gi);
Exemplos (snippet de execução):
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>
A partir da solução @ stephen-sweriduk (que foi a mais interessante para mim!), Eu a modifiquei levemente para torná-la mais genérica e reutilizável:
/**
* 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);
})
},
}
e depois
var stringToSplit = "people and_other/things";
var splitList = [" ", "_", "/"];
var splittedString=StringUtils.splitString(stringToSplit, splitList);
console.log(splitList, stringToSplit, splittedString);
que retribui como o original:
[ ' ', '_', '/' ] 'people and_other/things' [ 'people', 'and', 'other', 'things' ]
Uma maneira fácil de fazer isso é processar cada caractere da string com cada delimitador e criar uma matriz de divisões:
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;
};
Uso:
splix(string, delimiters...)
Exemplo:
splix("1.23--4", ".", "--")
Devoluções:
["1", "23", "4"]
Fornecerei uma implementação clássica para essa função. O código funciona em quase todas as versões do JavaScript e é de alguma forma ideal.
Apenas código puro:
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);
}
Você pode ver o código em execução no playground: https://codeguppy.com/code.html?IJI0E4OGnkyTZnoszAzf
Não sei o desempenho do RegEx, mas aqui está outra alternativa para o RegEx aproveita o HashSet nativo e trabalha com complexidade 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"]
Não é a melhor maneira, mas funciona para dividir com vários e diferentes separadores / delimitadores
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>
Eu uso o 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"]