Wytnij określony znak z ciągu


120

Jaki jest odpowiednik tej metody w JavaScriptC# :

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

C # przycina wybrany znak tylko na początku i na końcu ciągu!

Odpowiedzi:


155

Wystarczy jedna linia:

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

Ogólne rozwiązanie:

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

Jeśli dobrze zrozumiałem, chcesz usunąć określony znak tylko wtedy, gdy znajduje się na początku lub na końcu ciągu (np. ||fo||oo||||Powinien stać się foo||oo). Funkcję ad hoc można utworzyć w następujący sposób:

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

Przetestowałem tę funkcję za pomocą poniższego kodu:

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

3
To byłby fajny test dla odśmiecacza, ale nie polecałbym poddawać mu swoich klientów.
Sorensen

18

Możesz użyć wyrażenia regularnego, takiego jak:

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

AKTUALIZACJA:

Jeśli chcesz uogólnić to na funkcję, możesz wykonać następujące czynności:

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

aby to pytanie było aktualne:

tutaj jest podejście, które wybrałbym zamiast funkcji regex przy użyciu operatora spreadu 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);
}

Ulepszona wersja po komentarzu @fabian (obsługuje ciągi zawierające tylko ten sam znak)

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
Wiem, że wyrażenia regularne są tutaj przesadą, ale dlaczego miałbyś wybrać tę konkretną implementację?
Nicholas Shanks

2
ta implementacja, ponieważ osobiście uważam ją za dobrze czytelną. brak wyrażenia regularnego po prostu dlatego, że „drzewo” decyzyjne w silnikach wyrażeń regularnych jest znacznie większe. a zwłaszcza dlatego, że wyrażenia regularne używane do przycinania zawierają znaki zapytania, które prowadzą do cofania się w silniku wyrażeń regularnych. takie silniki często kompilują wzorzec w kod bajtowy, przypominający instrukcje maszynowe. silnik następnie wykonuje kod, przeskakując od instrukcji do instrukcji. gdy instrukcja się nie powiedzie, cofa się, aby znaleźć inny sposób dopasowania danych wejściowych. ergo dzieje się dużo więcej niż gdzie indziej.
Robin F.,

Dziękuję za odpowiedź, chociaż chciałem, żebyś wytłumaczył, dlaczego wybrałeś ten sposób, a nie inne sposoby robienia tego, które nie są regexowe - miałem nadzieję na coś więcej niż tylko „uważam to za czytelne”, jak sądzę.
Nicholas Shanks

1
@RobinF. myślisz, że findIndex () i reverse () nie zawierają pętli? Pomyśl jeszcze raz.
Andrew,

1
Dwie adnotacje: Ciąg zawierający tylko znak do przycięcia nie zostanie w ogóle przycięty. Drugi punkt jest taki: rozbicie łańcucha na tablicę za pomocą operatora spreadu zmyli babel i przekształci go w [].concat(string)nie pożądany wynik. Używanie Array.from(string)będzie działać.
Fabian

14

Wersja bez wyrażeń regularnych, która jest przyjemna dla oka:

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

Do przypadków użycia, w których jesteśmy pewni, że nie ma powtórzeń znaków poza krawędziami.


całkiem interesujące ... więc split zwraca niezdefiniowany element za równy każdemu rozdzielającemu separatorowiconst 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

Jeśli masz do czynienia z dłuższymi ciągami, uważam, że powinno to przewyższyć większość innych opcji, zmniejszając liczbę przydzielonych ciągów do zera lub jednego:

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'

Lub jeśli chcesz wyciąć z zestawu wielu znaków:

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'

EDYCJA: Dla zabawy, przycinaj słowa (zamiast pojedynczych znaków)

// 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
Wolę to rozwiązanie, ponieważ jest faktycznie wydajne, a nie tylko krótkie.
tekHedd

Zgadzam się, że powinno to być preferowane. Zastępuje odpowiedź, której udzieliłem.
TamusJRoyce

9

Może to przyciąć kilka znaków naraz:

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: Nie, nie bardzo. To wersja demonstracyjna, jeśli wkleisz ją w konsoli, po prostu wydrukuje wynik. Ale rozumiem, że może to być mylące, więc zredagowałem to.
marlar

2

Jeśli zdefiniujesz te funkcje w swoim programie, twoje ciągi będą miały ulepszoną wersję, trimktóra może przyciąć wszystkie podane znaki:

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)

Źródło

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


1

O ile mi wiadomo, jQuery nie ma wbudowanej funkcji, o którą pytasz. Jednak w javascript możesz po prostu użyć zamiany, aby zmienić zawartość swojego ciągu:

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

Spowoduje to zastąpienie wszystkich wystąpień | z niczym.


czy istnieje sposób na usunięcie | tylko na początku / końcu?
fubo

Właściwie myślę, że ten post pozwoli Ci najszybciej odpowiedzieć na Twoje pytanie: stackoverflow.com/questions/20196088/…
Ole Haugset

@fubo Jasne ... Wrzuć coś $takiego tylko na koniec: "||spam|||".replace(/\|+$/g, "")lub coś ^takiego tylko na początku:"||spam|||".replace(/^\|+/g, "")
ruffin

1

Ten przycina wszystkie ograniczniki wiodące i końcowe

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

Sugerowałbym przyjrzenie się lodashowi i temu, jak realizowali tę trimfunkcję.

Zobacz Lodash Trim, aby uzyskać dokumentację i źródło, aby zobaczyć dokładny kod, który wykonuje przycinanie.

Wiem, że to nie daje dokładnej odpowiedzi na twoje pytanie, ale myślę, że dobrze jest ustawić odniesienie do biblioteki na takie pytanie, ponieważ inni mogą uznać to za przydatne.


1
@TamusJRoyce to nie to samo
gdbdable

@devi Mogę się tylko zgodzić. dziękuje za komentarz. dobra odpowiedź, patrząc na narzędzie obsługiwane przez społeczność.
TamusJRoyce

1

Najlepszym sposobem rozwiązania tego zadania jest (podobnie jak w przypadku trimfunkcji 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: dlaczego opublikowałem swoją odpowiedź, skoro większość ludzi już to zrobiła? Ponieważ znalazłem „najlepszy” błąd we wszystkich odpowiedziach: wszyscy używali meta „+” zamiast „*”, ponieważ „ trimmuszą usunąć znaki, JEŚLI SĄ NA POCZĄTKU I / LUB KOŃCU, ale zwracają oryginalny ciąg w innym przypadku .


0

rozwijając odpowiedź @leaf, oto taka, która może mieć wiele znaków:

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

Podoba mi się rozwiązanie z @ Pho3niX83 ...

Rozszerzmy go o „słowo” zamiast „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);
};




-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
Nie nadpisuj domyślnego prototypu łańcucha lub poprosisz o późniejsze problemy. Utwórz własne oddzielne funkcje w innym miejscu.
rooby

-2

Wypróbuj tę metodę:

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


1
Czemu? Co to robi? Jak to działa? Odpowiedzi zawierające tylko kod są uważane za niską jakość w SO. Wyjaśnij swoją odpowiedź, aby OP i przyszli goście mogli się z niej uczyć.
Don't Panic
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.