Come divido una stringa con più separatori in JavaScript? Sto cercando di dividere su virgole e spazi ma, AFAIK, la funzione di divisione di JS supporta solo un separatore.
Come divido una stringa con più separatori in JavaScript? Sto cercando di dividere su virgole e spazi ma, AFAIK, la funzione di divisione di JS supporta solo un separatore.
Risposte:
Passa una regexp come parametro:
js> "Hello awesome, world!".split(/[\s,]+/)
Hello,awesome,world!
Modificato per aggiungere:
È possibile ottenere l'ultimo elemento selezionando la lunghezza dell'array meno 1:
>>> bits = "Hello awesome, world!".split(/[\s,]+/)
["Hello", "awesome", "world!"]
>>> bit = bits[bits.length - 1]
"world!"
... e se il modello non corrisponde:
>>> bits = "Hello awesome, world!".split(/foo/)
["Hello awesome, world!"]
>>> bits[bits.length - 1]
"Hello awesome, world!"
(hello world)|\|
non hanno ancora funzionato. Qualche idea?
È possibile passare una regex nell'operatore split di Javascript . Per esempio:
"1,2 3".split(/,| /)
["1", "2", "3"]
Oppure, se si desidera consentire a più separatori insieme di agire come uno solo:
"1, 2, , 3".split(/(?:,| )+/)
["1", "2", "3"]
(Devi usare le parentesi non catturanti (? :) perché altrimenti vengono ricucite nel risultato. O puoi essere intelligente come Aaron e usare una classe di personaggi.)
(Esempi testati in Safari + FF)
|
come mostra Jesse.
Un altro metodo semplice ma efficace è utilizzare ripetutamente split + join.
"a=b,c:d".split('=').join(',').split(':').join(',').split(',')
Fondamentalmente fare una divisione seguita da un join è come una sostituzione globale, quindi questo sostituisce ogni separatore con una virgola, quindi una volta che tutti sono stati sostituiti, esegue una divisione finale su una virgola
Il risultato dell'espressione precedente è:
['a', 'b', 'c', 'd']
Espandendo su questo potresti anche metterlo in una funzione:
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 usi molto questa funzionalità, potrebbe anche valere la pena considerare la possibilità di avvolgerla String.prototype.split
per comodità (penso che la mia funzione sia abbastanza sicura - l'unica considerazione è l'overhead aggiuntivo dei condizionali (minore) e il fatto che manca un'implementazione dell'argomento limite se viene passato un array).
Assicurati di includere la splitMulti
funzione se si utilizza semplicemente questo approccio al di sotto :) Vale anche la pena notare che alcune persone aggrottano le sopracciglia per estendere i built-in (poiché molte persone lo fanno male e possono verificarsi conflitti) quindi in caso di dubbio parla con qualcuno più senior prima di utilizzare questo o chiedi su 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"]
Godere!
for(var i = 0; i < tokens.length; i++)
e no for(var i = 1; i < tokens.length; i++)
?
tokens[1]
salvare un'iterazione tokens[0] == tempchar
e ci siamo separati tempchar
dopo aver ripetuto l'iterazione tokens
per finire. Aggiornerò la risposta di conseguenza grazie @tic :).
Semplificiamo: (aggiungi un "[] +" al tuo RegEx significa "1 o più")
Ciò significa che "+" e "{1,}" sono uguali.
var words = text.split(/[ .:;?!~,`"&|()<>{}\[\]\r\n/\\]+/); // note ' and - are kept
Metodo ingannevole:
var s = "dasdnk asd, (naks) :d skldma";
var a = s.replace('(',' ').replace(')',' ').replace(',',' ').split(' ');
console.log(a);//["dasdnk", "asd", "naks", ":d", "skldma"]
'('
per /(/g
sostituire tutti gli (
elementi - g
è la bandiera globale per RegExp - quindi cerca tutte le occorrenze di (
non prima
Per quelli di voi che desiderano una maggiore personalizzazione nella loro funzione di divisione, ho scritto un algoritmo ricorsivo che divide una determinata stringa con un elenco di caratteri su cui dividere. Ho scritto questo prima di vedere il post sopra. Spero che aiuti alcuni programmatori frustrati.
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);
L'esempio sopra restituisce: ["people", "and", "other", "things"]
Nota: la flatten
funzione è stata presa dal codice Rosetta
Potresti semplicemente raggruppare tutti i personaggi che vuoi usare come separatori singolarmente o collettivamente in un'espressione regolare e passarli alla funzione di divisione. Ad esempio potresti scrivere:
console.log( "dasdnk asd, (naks) :d skldma".split(/[ \(,\)]+/) );
E l'output sarà:
["dasdnk", "asd", "naks", ":d", "skldma"]
Salve, ad esempio, se hai diviso e sostituito in String 07:05:45 PM
var hour = time.replace("PM", "").split(":");
Risultato
[ '07', '05', '45' ]
Ecco un nuovo modo per raggiungere lo stesso in 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));
Si prega di notare in questa funzione:
source
Il risultato del codice sopra sarebbe:
a = "a=b,c:d"
array = ['=',',',':'];
for(i=0; i< array.length; i++){ a= a.split(array[i]).join(); }
questo restituirà la stringa senza un carattere speciale.
Il mio refactor della risposta di @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))
Trovo che uno dei motivi principali per cui ho bisogno è quello di dividere i percorsi dei file su entrambi /
e \
. È un po 'una regex complicata, quindi la posterò qui come riferimento:
var splitFilePath = filePath.split(/[\/\\]/);
Penso che sia più facile se specifichi ciò che vuoi lasciare, invece di ciò che vuoi rimuovere.
Come se volessi avere solo parole inglesi, puoi usare qualcosa del genere:
text.match(/[a-z'\-]+/gi);
Esempi (esegui snippet):
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 partire dalla soluzione @ stephen-sweriduk (che è stata la più interessante per me!), L'ho leggermente modificata per renderla più generica e riutilizzabile:
/**
* 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 poi
var stringToSplit = "people and_other/things";
var splitList = [" ", "_", "/"];
var splittedString=StringUtils.splitString(stringToSplit, splitList);
console.log(splitList, stringToSplit, splittedString);
che restituisce come l'originale:
[ ' ', '_', '/' ] 'people and_other/things' [ 'people', 'and', 'other', 'things' ]
Un modo semplice per farlo è quello di elaborare ogni carattere della stringa con ciascun delimitatore e creare una matrice delle divisioni:
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...)
Esempio:
splix("1.23--4", ".", "--")
Ritorna:
["1", "23", "4"]
Fornirò un'implementazione classica per una tale funzione. Il codice funziona in quasi tutte le versioni di JavaScript ed è in qualche modo ottimale.
Solo codice 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);
}
Puoi vedere il codice in esecuzione nel parco giochi: https://codeguppy.com/code.html?IJI0E4OGnkyTZnoszAzf
Non conosco le prestazioni di RegEx, ma ecco un'altra alternativa per RegEx che sfrutta HashSet nativo e funziona invece nella complessità 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"]
Non è il modo migliore ma funziona per dividere con separatori / delimitatori multipli e diversi
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>
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"]