Taglia un carattere specifico da una stringa


120

Qual è l' equivalente JavaScript di questo C#metodo:

var x = "|f|oo||"; 
var y = x.Trim('|'); //  "f|oo"

C # taglia il carattere selezionato solo all'inizio e alla fine della stringa!

Risposte:


155

Una riga è sufficiente:

var x = '|f|oo||';
var y = x.replace(/^\|+|\|+$/g, '');
document.write(x + '<br />' + y);

^\|+   beginning of the string, pipe, one or more times
|      or
\|+$   pipe, one or more times, end of the string

Una soluzione generale:

function trim (s, c) {
  if (c === "]") c = "\\]";
  if (c === "\\") c = "\\\\";
  return s.replace(new RegExp(
    "^[" + c + "]+|[" + c + "]+$", "g"
  ), "");
}

chars = ".|]\\";
for (c of chars) {
  s = c + "foo" + c + c + "oo" + c + c + c;
  console.log(s, "->", trim(s, c));
}


35

Se ho capito bene, vuoi rimuovere un carattere specifico solo se si trova all'inizio o alla fine della stringa (es: ||fo||oo||||dovrebbe diventare foo||oo). È possibile creare una funzione ad hoc come segue:

function trimChar(string, charToRemove) {
    while(string.charAt(0)==charToRemove) {
        string = string.substring(1);
    }

    while(string.charAt(string.length-1)==charToRemove) {
        string = string.substring(0,string.length-1);
    }

    return string;
}

Ho testato questa funzione con il codice seguente:

var str = "|f|oo||";
$( "#original" ).html( "Original String: '" + str + "'" );
$( "#trimmed" ).html( "Trimmed: '" + trimChar(str, "|") + "'" );

3
Questo sarebbe un test divertente per il garbage collector, ma non consiglierei di sottoporlo ai tuoi clienti.
Sorensen

18

Puoi usare un'espressione regolare come:

var x = "|f|oo||";
var y = x.replace(/^[\|]+|[\|]+$/g, "");
alert(y); // f|oo

AGGIORNARE:

Se desideri generalizzare questo in una funzione, puoi fare quanto segue:

var escapeRegExp = function(strToEscape) {
    // Escape special characters for use in a regular expression
    return strToEscape.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
};

var trimChar = function(origString, charToTrim) {
    charToTrim = escapeRegExp(charToTrim);
    var regEx = new RegExp("^[" + charToTrim + "]+|[" + charToTrim + "]+$", "g");
    return origString.replace(regEx, "");
};

var x = "|f|oo||";
var y = trimChar(x, "|");
alert(y); // f|oo

17

per mantenere aggiornata questa domanda:

ecco un approccio che sceglierei rispetto alla funzione regex utilizzando l'operatore di diffusione ES6.

function trimByChar(string, character) {
  const first = [...string].findIndex(char => char !== character);
  const last = [...string].reverse().findIndex(char => char !== character);
  return string.substring(first, string.length - last);
}

Versione migliorata dopo il commento di @fabian (può gestire solo stringhe contenenti lo stesso carattere)

function trimByChar(string, character) {
  const arr = Array.from(string);
  const first = arr.indexOf(character);
  const last = arr.reverse().indexOf(character);
  return string.substring(first + 1, string.length - last - 1);
}

2
So che le regex sono eccessive qui, ma perché sceglieresti questa particolare implementazione?
Nicholas Shanks

2
questa implementazione perché personalmente la trovo ben leggibile. nessuna regex semplicemente perché l '"albero" decisionale all'interno dei motori di regex è molto più grande. e soprattutto perché le regex utilizzate per il trimming contengono caratteri di query che portano al backtracking all'interno del motore di regex. tali motori spesso compilano il modello in byte-code, simile alle istruzioni della macchina. il motore quindi esegue il codice, saltando da un'istruzione all'altra. quando un'istruzione fallisce, torna indietro per trovare un altro modo per abbinare l'input. ergo molto di più in corso di nec.
Robin F.

Grazie per la risposta, anche se volevo che spiegassi perché avresti scelto questo rispetto ad altri modi non regex per farlo - speravo in qualcosa di più che semplicemente "lo trovo leggibile", suppongo.
Nicholas Shanks

1
@RobinF. pensi che findIndex () e reverse () non contengano loop? Pensa di nuovo.
Andrew

1
Due annotazioni: una stringa contenente solo il carattere da tagliare non verrà tagliata affatto. L'altro punto è: l'esplosione della stringa in un array con l'operatore spread confonderà babel e la trasformerà in un [].concat(string)risultato non desiderato. L'utilizzo Array.from(string)funzionerà.
Fabian

14

Una versione senza regex che è facile da vedere:

const trim = (str, chars) => str.split(chars).filter(Boolean).join(chars);

Per casi d'uso in cui siamo certi che non ci siano ripetizioni dei caratteri fuori dai bordi.


abbastanza interessante ... quindi split restituisce un elemento indefinito per uguale a ciascun delimitatore divisoconst trim = (str, chars) => str.split(chars).filter(x => { Boolean(x); console.log(typeof(x), x, Boolean(x)); }).join(chars); const str = "#//#//abc#//test#//end#//"; console.log(trim(str, '#//'));
TamusJRoyce

10

Se hai a che fare con stringhe più lunghe, credo che questo dovrebbe superare la maggior parte delle altre opzioni riducendo il numero di stringhe allocate a zero o uno:

function trim(str, ch) {
    var start = 0, 
        end = str.length;

    while(start < end && str[start] === ch)
        ++start;

    while(end > start && str[end - 1] === ch)
        --end;

    return (start > 0 || end < str.length) ? str.substring(start, end) : str;
}

// Usage:
trim('|hello|world|', '|'); // => 'hello|world'

Oppure, se vuoi tagliare da un insieme di più caratteri:

function trimAny(str, chars) {
    var start = 0, 
        end = str.length;

    while(start < end && chars.indexOf(str[start]) >= 0)
        ++start;

    while(end > start && chars.indexOf(str[end - 1]) >= 0)
        --end;

    return (start > 0 || end < str.length) ? str.substring(start, end) : str;
}

// Usage:
trimAny('|hello|world   ', [ '|', ' ' ]); // => 'hello|world'
// because '.indexOf' is used, you could also pass a string for the 2nd parameter:
trimAny('|hello| world  ', '| '); // => 'hello|world'

EDIT: per divertimento, ritaglia le parole (piuttosto che i singoli caratteri)

// Helper function to detect if a string contains another string
//     at a specific position. 
// Equivalent to using `str.indexOf(substr, pos) === pos` but *should* be more efficient on longer strings as it can exit early (needs benchmarks to back this up).
function hasSubstringAt(str, substr, pos) {
    var idx = 0, len = substr.length;

    for (var max = str.length; idx < len; ++idx) {
        if ((pos + idx) >= max || str[pos + idx] != substr[idx])
            break;
    }

    return idx === len;
}

function trimWord(str, word) {
    var start = 0,
        end = str.length,
        len = word.length;

    while (start < end && hasSubstringAt(str, word, start))
        start += word.length;

    while (end > start && hasSubstringAt(str, word, end - len))
        end -= word.length

    return (start > 0 || end < str.length) ? str.substring(start, end) : str;
}

// Usage:
trimWord('blahrealmessageblah', 'blah');

1
Preferisco questa soluzione perché è, infatti, effettivamente efficiente, piuttosto che breve.
tekHedd

Sono d'accordo che dovrebbe essere preferito. Sostituisce una risposta che avevo dato.
TamusJRoyce

9

Questo può tagliare più caratteri alla volta:

String.prototype.trimChars = function (c) {
  var re = new RegExp("^[" + c + "]+|[" + c + "]+$", "g");
  return this.replace(re,"");
}

var x = "|f|oo||"; 
x =  x.trimChars('|'); // f|oo

var y = "..++|f|oo||++..";
y = y.trimChars('|.+'); // f|oo

var z = "\\f|oo\\"; // \f|oo\

// For backslash, remember to double-escape:
z = z.trimChars("\\\\"); // f|oo

@fubo: No, non proprio. È una demo, se la incolli in una console stamperà solo il risultato. Ma capisco che possa creare confusione, quindi l'ho modificato.
marlar

2

Se definisci queste funzioni nel tuo programma, le tue stringhe avranno una versione aggiornata trimche può tagliare tutti i caratteri dati:

String.prototype.trimLeft = function(charlist) {
	if (charlist === undefined)
	charlist = "\s";

	return this.replace(new RegExp("^[" + charlist + "]+"), "");
};

String.prototype.trim = function(charlist) {
	return this.trimLeft(charlist).trimRight(charlist);
};

String.prototype.trimRight = function(charlist) {
	if (charlist === undefined)
	charlist = "\s";

	return this.replace(new RegExp("[" + charlist + "]+$"), "");
};

var withChars = "/-center-/"
var withoutChars = withChars.trim("/-")
document.write(withoutChars)

fonte

https://www.sitepoint.com/trimming-strings-in-javascript/


1

Per quanto ne so, jQuery non ha una funzione incorporata nel metodo che stai chiedendo. Con javascript, tuttavia, puoi semplicemente usare sostituisci per modificare il contenuto della tua stringa:

x.replace(/|/i, ""));

Questo sostituirà tutte le occorrenze di | con niente.


c'è un modo per rimuovere | solo all'inizio / fine?
fubo

Io in realtà penso questo post ti porterà la più fino a velocità sulla vostra domanda: stackoverflow.com/questions/20196088/...
Ole Haugset

@fubo Certo ... getta un $come questo solo alla fine: "||spam|||".replace(/\|+$/g, "")o un ^come questo solo all'inizio:"||spam|||".replace(/^\|+/g, "")
ruffin

1

Questo taglia tutti i delimitatori iniziali e finali

const trim = (str, delimiter) => {
  const pattern = `[^\\${delimiter}]`;
  const start = str.search(pattern);
  const stop = str.length - str.split('').reverse().join('').search(pattern);
  return str.substring(start, stop);
}

const test = '||2|aaaa12bb3ccc|||||';
console.log(trim(test, '|')); // 2|aaaa12bb3ccc

1

Suggerirei di guardare lodash e come hanno implementato la trimfunzione.

Vedi Lodash Trim per la documentazione e il sorgente per vedere il codice esatto che esegue il taglio.

So che questo non fornisce una risposta esatta alla tua domanda, ma penso che sia bene impostare un riferimento a una libreria su una domanda del genere poiché altri potrebbero trovarla utile.


1
@TamusJRoyce non è lo stesso
gdbdable

@devi posso solo essere d'accordo. Grazie per il commento. buona risposta cercando in uno strumento supportato dalla comunità.
TamusJRoyce

1

Il modo migliore per risolvere questa attività è (simile alla trimfunzione PHP ):

function trim( str, charlist ) {
  if ( typeof charlist == 'undefined' ) {
    charlist = '\\s';
  }
  
  var pattern = '^[' + charlist + ']*(.*?)[' + charlist + ']*$';
  
  return str.replace( new RegExp( pattern ) , '$1' )
}

document.getElementById( 'run' ).onclick = function() {
  document.getElementById( 'result' ).value = 
  trim( document.getElementById( 'input' ).value,
  document.getElementById( 'charlist' ).value);
}
<div>
  <label for="input">Text to trim:</label><br>
  <input id="input" type="text" placeholder="Text to trim" value="dfstextfsd"><br>
  <label for="charlist">Charlist:</label><br>
  <input id="charlist" type="text" placeholder="Charlist" value="dfs"><br>
  <label for="result">Result:</label><br>
  <input id="result" type="text" placeholder="Result" disabled><br>
  <button type="button" id="run">Trim it!</button>
</div>

PS: perché ho pubblicato la mia risposta, quando la maggior parte delle persone l'ha già fatto prima? Perché ho trovato l'errore "migliore" in tutte le risposte: tutte hanno utilizzato il meta '+' invece di '*', perché trimdevono rimuovere i caratteri SE SONO IN INIZIO E / O IN FINE, ma restituisce la stringa originale in altri casi .


0

espandendo la risposta di @leaf, eccone una che può richiedere più caratteri:

var trim = function (s, t) {
  var tr, sr
  tr = t.split('').map(e => `\\\\${e}`).join('')
  sr = s.replace(new RegExp(`^[${tr}]+|[${tr}]+$`, 'g'), '')
  return sr
}

0

Mi piace la soluzione di @ Pho3niX83 ...

Estendiamolo con "word" invece di "char" ...

function trimWord(_string, _word) {

    var splitted = _string.split(_word);

    while (splitted.length && splitted[0] === "") {
        splitted.shift();
    }
    while (splitted.length && splitted[splitted.length - 1] === "") {
        splitted.pop();
    }
    return splitted.join(_word);
};

0
function trim(text, val) {
    return text.replace(new RegExp('^'+val+'+|'+val+'+$','g'), '');
}



-1
String.prototype.TrimStart = function (n) {
    if (this.charAt(0) == n)
        return this.substr(1);
};

String.prototype.TrimEnd = function (n) {
    if (this.slice(-1) == n)
        return this.slice(0, -1);
};


1
Non sovrascrivere il prototipo di stringa predefinito o stai chiedendo problemi in seguito. Crea le tue funzioni separate altrove.
rooby

-2

Prova questo metodo:

var a = "anan güzel mi?";
if (a.endsWith("?"))   a = a.slice(0, -1);  
document.body.innerHTML = a;


1
Perché? Cosa fa questo? Come funziona? Le risposte di solo codice sono considerate di bassa qualità in SO. Spiega la tua risposta in modo che l'OP e tutti i futuri visitatori possano imparare da essa.
Don't Panic
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.