¿Cómo divido una cadena con múltiples separadores en JavaScript? Estoy tratando de dividir tanto en comas como en espacios, pero, AFAIK, la función de división de JS solo admite un separador.
¿Cómo divido una cadena con múltiples separadores en JavaScript? Estoy tratando de dividir tanto en comas como en espacios, pero, AFAIK, la función de división de JS solo admite un separador.
Respuestas:
Pase una expresión regular como parámetro:
js> "Hello awesome, world!".split(/[\s,]+/)
Hello,awesome,world!
Editado para agregar:
Puede obtener el último elemento seleccionando la longitud de la matriz menos 1:
>>> bits = "Hello awesome, world!".split(/[\s,]+/)
["Hello", "awesome", "world!"]
>>> bit = bits[bits.length - 1]
"world!"
... y si el patrón no coincide:
>>> bits = "Hello awesome, world!".split(/foo/)
["Hello awesome, world!"]
>>> bits[bits.length - 1]
"Hello awesome, world!"
(hello world)|\|
cuales todavía no funcionan. ¿Algunas ideas?
Puede pasar una expresión regular al operador dividido de Javascript . Por ejemplo:
"1,2 3".split(/,| /)
["1", "2", "3"]
O, si desea permitir que varios separadores juntos actúen como uno solo:
"1, 2, , 3".split(/(?:,| )+/)
["1", "2", "3"]
(Tienes que usar los parensos que no capturan (? :) porque de lo contrario se vuelven a unir en el resultado. O puedes ser inteligente como Aaron y usar una clase de personaje).
(Ejemplos probados en Safari + FF)
|
como muestra Jesse.
Otro método simple pero efectivo es usar split + join repetidamente.
"a=b,c:d".split('=').join(',').split(':').join(',').split(',')
Esencialmente, hacer una división seguida de una unión es como un reemplazo global, por lo que esto reemplaza cada separador con una coma y luego, una vez que todos se reemplazan, se realiza una división final en coma
El resultado de la expresión anterior es:
['a', 'b', 'c', 'd']
Ampliando esto, también podría colocarlo en una función:
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"]
Si usa mucho esta funcionalidad, incluso podría valer la pena considerar el ajuste String.prototype.split
por conveniencia (creo que mi función es bastante segura; la única consideración es la sobrecarga adicional de los condicionales (menores) y el hecho de que carece de una implementación del argumento límite si se pasa una matriz)
Asegúrese de incluir la splitMulti
función si utiliza este enfoque para el siguiente simplemente lo envuelve :). También vale la pena señalar que algunas personas fruncen el ceño al extender los elementos integrados (ya que muchas personas lo hacen mal y pueden ocurrir conflictos), por lo que si tiene dudas, hable con alguien más mayor antes de usar esto o pregunte por 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"]
¡Disfrutar!
for(var i = 0; i < tokens.length; i++)
y no for(var i = 1; i < tokens.length; i++)
?
tokens[1]
a guardar una iteración a medida que tokens[0] == tempchar
nos separamos tempchar
después de iterar tokens
para terminar. Actualizaré la respuesta en consecuencia gracias @tic :).
Vamos a mantenerlo simple: (agregar un "[] +" a su RegEx significa "1 o más")
Esto significa que "+" y "{1,}" son lo mismo.
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
reemplazar todos los (
elementos, g
es el indicador global de RegExp, por lo que busca todas las apariciones de (
no el primero
Para aquellos de ustedes que desean una mayor personalización en su función de división, escribí un algoritmo recursivo que divide una cadena dada con una lista de caracteres para dividir. Escribí esto antes de ver la publicación anterior. Espero que ayude a algunos 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);
El ejemplo anterior devuelve: ["people", "and", "other", "things"]
Nota: la flatten
función se tomó del Código Rosetta
Puede agrupar todos los caracteres que desea utilizar como separadores, ya sea de forma individual o colectiva, en una expresión regular y pasarlos a la función de división. Por ejemplo, podrías escribir:
console.log( "dasdnk asd, (naks) :d skldma".split(/[ \(,\)]+/) );
Y la salida será:
["dasdnk", "asd", "naks", ":d", "skldma"]
Hola, por ejemplo, si has dividido y reemplazado en String 07:05:45 PM
var hour = time.replace("PM", "").split(":");
Resultado
[ '07', '05', '45' ]
Aquí hay una nueva forma de lograr lo mismo en 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));
Tenga en cuenta en esta función:
source
El resultado del código anterior sería:
a = "a=b,c:d"
array = ['=',',',':'];
for(i=0; i< array.length; i++){ a= a.split(array[i]).join(); }
Esto devolverá la cadena sin un carácter especial.
Mi refactor de @Brian responde
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))
Creo que una de las principales razones por las que necesito esto es dividir las rutas de los archivos en ambos /
y \
. Es una expresión regular un poco complicada, así que la publicaré aquí como referencia:
var splitFilePath = filePath.split(/[\/\\]/);
Creo que es más fácil si especificas lo que quieres dejar, en lugar de lo que quieres eliminar.
Como si quisieras tener solo palabras en inglés, puedes usar algo como esto:
text.match(/[a-z'\-]+/gi);
Ejemplos (ejecutar fragmento):
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 de la solución @ stephen-sweriduk (¡eso fue lo más interesante para mí!), La modifiqué ligeramente para hacerla más genérica y reutilizable:
/**
* 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);
})
},
}
y entonces
var stringToSplit = "people and_other/things";
var splitList = [" ", "_", "/"];
var splittedString=StringUtils.splitString(stringToSplit, splitList);
console.log(splitList, stringToSplit, splittedString);
que devuelve como el original:
[ ' ', '_', '/' ] 'people and_other/things' [ 'people', 'and', 'other', 'things' ]
Una manera fácil de hacer esto es procesar cada carácter de la cadena con cada delimitador y construir una matriz de divisiones:
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...)
Ejemplo:
splix("1.23--4", ".", "--")
Devoluciones:
["1", "23", "4"]
Proporcionaré una implementación clásica para dicha función. El código funciona en casi todas las versiones de JavaScript y de alguna manera es óptimo.
Solo 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);
}
Puede ver el código que se ejecuta en el patio de recreo: https://codeguppy.com/code.html?IJI0E4OGnkyTZnoszAzf
No conozco el rendimiento de RegEx, pero aquí hay otra alternativa para que RegEx aprovecha HashSet nativo y funciona en su lugar con complejidad 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"]
No es la mejor manera, pero funciona para dividir con separadores / delimitadores múltiples y diferentes
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>
Yo uso 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"]