JavaScript siekaj / wycinaj / przycinaj ostatni znak w ciągu


1973

Mam ciąg 12345.00i chciałbym, aby powrócił 12345.0.

Patrzyłem trim, ale wygląda na to, że to tylko przycinanie białych znaków, a slicenie wiem, jak to by działało. Jakieś sugestie?


36
Czy zależy ci na zaokrąglaniu? 12345.46 = 12345.5 lub 12345.4?
RSolberg

9
Czy wiesz, co to jest przyrostek, czy chcesz podzielić i usunąć ostatnie słowo na podstawie podkreślenia?
C

65
Ho ho ho, @RSolberg: nie można zaokrąglić sznurka!
Ziggy,

50
@Ziggy mówi co? Math.round('0.5') === 1;)
TWiStErRob

16
@TWiStErRob Oh JavaScript, co mam z tobą zrobić? * kręci głową *
Chuck Le Butt,

Odpowiedzi:


3211

Możesz użyć funkcji podciągu :

let str = "12345.00";
str = str.substring(0, str.length - 1);
console.log(str);

To jest akceptowana odpowiedź, ale zgodnie z poniższymi rozmowami składnia plastra jest znacznie bardziej przejrzysta:

let str = "12345.00";
str = str.slice(0, -1); 
console.log(str);


23
@Kheu - notacja plastra jest dla mnie znacznie czystsza. Wcześniej korzystałem z wersji substring. Dzięki!
Matt Ball

32
wybacz mi, jeśli się mylę, ale czy nie musisz ponownie przypisywać wartości str.substring do str? Jakstr = str.substring(0, str.length -1);
Doug Molineux,

10
Wszystkie metody slice& substringsą takie same; z wyjątkiem tego, że slice()akceptuje indeks ujemny w stosunku do końca łańcucha, ale nie substring, powoduje out-of-boundbłąd
Amol M Kulkarni

20
W przypadku, gdy ktoś się zastanawia, substringjest o 11% szybszy niż slice. jsperf.com/js-slice-vs-substring-test
BenR

19
substring to szalone mikrooptymalizacje, których nie sądzę, że powinieneś robić. Najpierw zmaksymalizuj dla czytelności. W razie potrzeby zoptymalizuj nisko wiszące owoce.
Alfred

1306

Możesz użyć plasterka ! Musisz tylko upewnić się, że wiesz, jak go używać. Dodatnie liczby # odnoszą się do początku, liczby ujemne odnoszą się do końca.

js>"12345.00".slice(0,-1)
12345.0

75
W porównaniu do przyjętego rozwiązania jest to o wiele bardziej eleganckie i może być używane nawet z dynamicznie tworzonymi łańcuchami
Sameer Alibhai

1
Lubię to, ponieważ bawi się myśleniem php o funkcji substr, łatwiej zapamiętuje i pisze w locie.
pathfinder

2
@SameerAlibhai Zgadzam się z tobą, ale czy nie substringmożna zastosować tej metody również w przypadku ciągów dynamicznych? Korzystając z str. Length, aby dynamicznie uzyskać długość?
Doug Molineux,

Należy dodać, że pierwszy indeks jest włączający, a drugi wyłączny.
Miscreant,

@KevinBeal możesz po prostu użyć F12 w głównych przeglądarkach i wprowadzić go w konsoli, działa na dowolnej stronie, a nawet masz kontekst i możesz mieć załadowane biblioteki.
TWiStErRob

263

Możesz użyć metody podciągów obiektów łańcuchowych JavaScript:

s = s.substring(0, s.length - 4)

Bezwarunkowo usuwa ostatnie cztery znaki z łańcucha s.

Jeśli jednak chcesz warunkowo usunąć ostatnie cztery znaki, tylko jeśli są one dokładnie _bar :

var re = /_bar$/;
s.replace(re, "");

107
slicetu jest lepiej. s.slice(0, -4)
Tim Down

12
Alternatywnie: s.slice (0, - „_ bar” .length) (przydatne, jeśli nie chce się na stałe kodować liczby znaków)
Mahn

3
Podoba mi się ten, ponieważ pomaga również w zastąpieniu określonego zakończenia.
Mike Graf

162

Najłatwiejszą metodą jest użycie slicemetody ciągu, która pozwala na pozycje ujemne (odpowiadające przesunięciom z końca łańcucha):

const s = "your string";
const withoutLastFourChars = s.slice(0, -4);

Jeśli potrzebujesz czegoś bardziej ogólnego, aby usunąć wszystko po ostatnim podkreśleniu (włącznie z nim), możesz wykonać następujące czynności (pod warunkiem, sże zawiera on co najmniej jeden znak podkreślenia):

const s = "your_string";
const withoutLastChunk = s.slice(0, s.lastIndexOf("_"));
console.log(withoutLastChunk);


67

W przypadku liczby takiej jak twój przykład zaleciłbym zrobienie tego ponad substring:

console.log(parseFloat('12345.00').toFixed(1));

Zauważ, że to faktycznie zaokrągli liczbę, co, jak sądzę, jest pożądane, ale może nie:

console.log(parseFloat('12345.46').toFixed(1));


11
+1 Tego potrzebuje OP, zapomnij o fałszywym założeniu, że istnieją ciągi do przycięcia.
naugtur,

2
To nie jest fałszywe założenie, OP mówi o ciągach znaków. Twoje jest fałszywym założeniem, ponieważ OP nie mówi o zaokrąglaniu liczb.
Fernando

30

Korzystanie z funkcji wycinka JavaScript:

let string = 'foo_bar';
string = string.slice(0, -4); // Slice off last four characters here
console.log(string);

Można tego użyć do usunięcia „_bar” na końcu łańcucha dowolnej długości.


19

Wyrażenie regularne jest tym, czego szukasz:

let str = "foo_bar";
console.log(str.replace(/_bar$/, ""));


Twoje rozwiązanie działa, ale odpowiedź Alexa jest bardziej wyczerpująca. Więc zaakceptuję jego. Dzięki!
Albert

1
To rozwiązuje związany z tym problem warunkowego usuwania zamiast ślepego obcinania
Aaron



9

Użyj wyrażenia regularnego:

let aStr = "12345.00";
aStr = aStr.replace(/.$/, '');
console.log(aStr);


Poza tym, że nie obsługuje Unicode, to również nie pasuje do podziałów linii.
user4642212

7
  1. (. *), przechwytuje dowolną postać wiele razy

console.log("a string".match(/(.*).$/)[1]);

  1. ., w tym przypadku dopasowuje ostatni znak

console.log("a string".match(/(.*).$/));

  1. $, dopasowuje koniec łańcucha

console.log("a string".match(/(.*).{2}$/)[1]);


9
Podoba mi się, ponieważ pomimo .splice () znalazłeś sposób na użycie wyrażenia regularnego.
QueueHammer

Poza tym, że nie obsługuje Unicode, to również nie pasuje do podziałów linii.
user4642212


5

Oto alternatywa, której nie widziałem w innych odpowiedziach, dla zabawy.

var strArr = "hello i'm a string".split("");
strArr.pop();
document.write(strArr.join(""));

Nie jest tak czytelny ani prosty jak plasterek lub podciąg, ale pozwala grać z ciągiem przy użyciu kilku fajnych metod tablicowych, więc warto wiedzieć.


4
debris = string.split("_") //explode string into array of strings indexed by "_"

debris.pop(); //pop last element off the array (which you didn't want)

result = debris.join("_"); //fuse the remainng items together like the sun


3

Jeśli chcesz zrobić ogólne zaokrąglanie liczb zmiennoprzecinkowych, zamiast przycinać ostatni znak:

var float1 = 12345.00,
    float2 = 12345.4567,
    float3 = 12345.982;

var MoreMath = {
    /**
     * Rounds a value to the specified number of decimals
     * @param float value The value to be rounded
     * @param int nrDecimals The number of decimals to round value to
     * @return float value rounded to nrDecimals decimals
     */
    round: function (value, nrDecimals) {
        var x = nrDecimals > 0 ? 10 * parseInt(nrDecimals, 10) : 1;
        return Math.round(value * x) / x;
    }
}

MoreMath.round(float1, 1) => 12345.0
MoreMath.round(float2, 1) => 12345.5
MoreMath.round(float3, 1) => 12346.0

EDYCJA: Wydaje się, że istnieje wbudowana funkcja do tego, jak zauważa Paolo. To rozwiązanie jest oczywiście znacznie czystsze niż moje. Użyj parseFloat, a następnie toFixed




1

Wydajność

Dzisiaj 2020.05.13 przeprowadzam testy wybranych rozwiązań na Chrome v81.0, Safari v13.1 i Firefox v76.0 na MacOs High Sierra 10.13.6.

Wnioski

  • slice(0,-1)(D) jest szybki i najszybszym rozwiązaniem dla krótkich i długich ciągów i zaleca się jako szybkie rozwiązanie cross-browser
  • rozwiązania oparte na substring(C) i substr(E) są szybkie
  • rozwiązania oparte na wyrażeniach regularnych (A, B) są wolne / średnio szybkie
  • rozwiązania B, F i G są wolne dla długich łańcuchów
  • rozwiązanie F jest najwolniejsze dla krótkich łańcuchów, G jest najwolniejsze dla długich łańcuchów

wprowadź opis zdjęcia tutaj

Detale

Przeprowadzam dwa testy dla rozwiązań A , B , C , D , E ( ext ), F , G (mój)

  • dla 8-znakowego krótkiego ciągu (od pytania OP) - możesz go uruchomić TUTAJ
  • na łańcuch 1M - możesz go uruchomić TUTAJ

Rozwiązania są przedstawione poniżej

Oto przykładowe wyniki dla Chrome dla krótkiego ciągu

wprowadź opis zdjęcia tutaj


1

Pamiętaj, że String.prototype.{ split, slice, substr, substring }działają na ciągach kodowanych w UTF-16

Żadna z poprzednich odpowiedzi nie obsługuje Unicode. Łańcuchy są kodowane jako UTF-16 w większości nowoczesnych silników JavaScript, ale wyższe punkty kodu Unicode wymagają par zastępczych , więc starsze, wcześniej istniejące metody łańcuchów działają na jednostkach kodu UTF-16, a nie punktach kodu Unicode.

const string = "ẞ🦊";

console.log(string.slice(0, -1)); // "ẞ\ud83e"
console.log(string.substr(0, string.length - 1)); // "ẞ\ud83e"
console.log(string.substring(0, string.length - 1)); // "ẞ\ud83e"
console.log(string.replace(/.$/, "")); // "ẞ\ud83e"
console.log(string.match(/(.*).$/)[1]); // "ẞ\ud83e"

const utf16Chars = string.split("");

utf16Chars.pop();
console.log(utf16Chars.join("")); // "ẞ\ud83e"

Ponadto odpowiedzi RegExp nie pasują do podziałów linii na końcu w ich obecnej formie:

const string = "Hello, world!\n";

console.log(string.replace(/.$/, "").endsWith("\n")); // true
console.log(string.match(/(.*).$/) === null); // true


Użyj iteratora ciągów do iteracji znaków

Kod obsługujący Unicode wykorzystuje iterator łańcucha; widzieć Array.fromi ...rozprzestrzeniać się . string[Symbol.iterator]można użyć (np. zamiaststring ).

Zobacz także Jak podzielić ciąg znaków Unicode na znaki w JavaScript .

Przykłady:

const string = "ẞ🦊";

console.log(Array.from(string).slice(0, -1).join("")); // "ẞ"
console.log([
  ...string
].slice(0, -1).join("")); // "ẞ"

Użyj flag si unaRegExp

Te dotAlllub sflag marki .dopasować znaki przerwy linii, unicodeczy uflaga umożliwia pewne funkcje związane z Unicode.

Przykłady:

const unicodeString = "ẞ🦊",
  lineBreakString = "Hello, world!\n";

console.log(lineBreakString.replace(/.$/s, "").endsWith("\n")); // false
console.log(lineBreakString.match(/(.*).$/s) === null); // false
console.log(unicodeString.replace(/.$/su, "")); // ẞ
console.log(unicodeString.match(/(.*).$/su)[1]); // ẞ

// Now `split` can be made Unicode-aware:

const unicodeCharacterArray = unicodeString.split(/(?:)/su),
  lineBreakCharacterArray = lineBreakString.split(/(?:)/su);

unicodeCharacterArray.pop();
lineBreakCharacterArray.pop();
console.log(unicodeCharacterArray.join("")); // "ẞ"
console.log(lineBreakCharacterArray.join("").endsWith("\n")); // false


Zauważ, że niektóre grafemy składają się z więcej niż jednego punktu kodowego, np. 🏳️‍🌈Który składa się z sekwencji 🏳(U + 1F3F3), VS16(U + FE0F) , ZWJ(U + 200D) , 🌈(U + 1F308). Tutaj nawet Array.frompodzieli to na cztery „postacie”. Dopasowanie ich jest możliwe dzięki właściwości Unicode, która ucieka od propozycji właściwości sekwencji .


-1

W przypadkach, gdy chcesz usunąć coś, co znajduje się blisko końca łańcucha (w przypadku łańcuchów o zmiennej wielkości), możesz połączyć slice () i substr ().

Miałem ciąg znaków ze znacznikami, zbudowany dynamicznie, z listą tagów kotwicy oddzielonych przecinkiem. Ciąg był podobny do:

var str = "<a>text 1,</a><a>text 2,</a><a>text 2.3,</a><a>text abc,</a>";

Aby usunąć ostatni przecinek, wykonałem następujące czynności:

str = str.slice(0, -5) + str.substr(-4);

-3

Spróbuj tego:

<script>
    var x="foo_foo_foo_bar";
    for (var i=0; i<=x.length; i++) {
        if (x[i]=="_" && x[i+1]=="b") {
            break;
        }
        else {
            document.write(x[i]);
        }
    }
</script>

Możesz także wypróbować działający przykład na żywo pod adresem http://jsfiddle.net/informativejavascript/F7WTn/87/ .


3
Dzięki kamal. Jednak zaznaczyłem powyższą odpowiedź jako zaakceptowaną dla moich potrzeb. Zwróć uwagę na zielony znacznik wyboru powyżej. Chociaż sprawdziłem twój kod. :) Teraz, w mojej sytuacji, znam tylko wspólną sekwencję znaków końcowych. Lepiej po prostu zacząć sprawdzanie od końca łańcucha. Twoja sugestia nie powiedzie się, jeśli mam ciąg znaków, który wygląda jak „foo_b_bar”, i chcę tylko usunąć ostatni „_bar”. W każdym razie dzięki! Zadawanie pytań ponad 2 lata temu jest dość interesującym doświadczeniem i nadal otrzymuję odpowiedzi na nie dzisiaj. :)
Albert

-4

@Jason S:

Możesz użyć plasterka! Musisz tylko upewnić się, że wiesz, jak go używać. Dodatnie liczby # odnoszą się do początku, liczby ujemne odnoszą się do końca.

js> „12345.00” .slice (0, -1) 12345.0

Przepraszam za moje grafiki, ale post został wcześniej oznaczony jako „jquery”. Tak więc nie możesz używać slice () wewnątrz jQuery, ponieważ slice () jest metodą jQuery do operacji z elementami DOM, a nie podciągami ... Innymi słowy odpowiedź @Jon Erickson sugeruje naprawdę idealne rozwiązanie.

Jednak twoja metoda będzie działała poza funkcją jQuery, w prostym JavaScript. Muszę powiedzieć ze względu na ostatnią dyskusję w komentarzach, że jQuery jest znacznie częściej odnawialnym rozszerzeniem JS niż jego najbardziej znany ECMAScript.

Istnieją również dwie metody:

jak nasz:

string.substring(from,to) plus plus, jeśli indeks „do” nulled zwraca resztę ciągu. więc: string.substring(from) pozytywne lub negatywne ...

i niektóre inne - substr () - które zapewniają zakres podciągów i „długość” mogą być dodatnie: string.substr(start,length)

Również niektórzy opiekunowie sugerują, że ostatnia metoda string.substr(start,length)nie działa lub działa z błędem dla MSIE.


3
Co masz na myśli? String.prototype.slicejest rodzimą metodą
naugtur,

to tylko to, co powiedziałeś. Metoda rodzima Javascript, ale także slice()metoda jQuery do manipulacji DOM: jQuery API: .slice () . I PEWNE, że MOŻNA ZROBIĆ jak polimorficzne dziedziczenie JS Array.slice (), ale są to dwie różne metody i myślę, że należy je rozróżnić. Jest to więc tylko przybliżenie tej wiedzy.
szybki

12
Jeśli wywołasz .slicezmienną, która jest łańcuchem, zrobi to, co chciał OP. Nie ma znaczenia, czy jest to „wewnątrz jQuery” i nie ma żadnego sposobu, by „ingerował” w jakikolwiek sposób, chyba że nadpiszesz String.prototypejQuery, co, jestem pewien, uniemożliwi działanie KAŻDEGO kodu javascript. Twoja odpowiedź mówi tylko, że inna odpowiedź nie jest dobra, a argument, który podałeś, jest nieprawidłowy.
naugtur,

1
Mogę się zgodzić z @naugtur, że ta odpowiedź jest błędna, jQuery nie stosuje metody wycinania łańcucha.
Rebbot

1
Myślę, że celem naugtur było po prostu to, że możliwe, że możesz skończyć z łańcuchem owiniętym przez obiekt jQuery (np. Jeśli wykonasz jakieś wymyślne .datamanipulacje i skończysz z tym „łańcuchem”), który jeśli slicego wywołałeś , nie zrobiłby tego, co chcesz. To powiedziawszy, to nie jest naprawdę pomocna odpowiedź.
mAAdhaTTah

-8

Użyj podciągów, aby uzyskać wszystko po lewej stronie _bar. Ale najpierw musisz pobrać instrukcję _bar w ciągu:

str.substring(3, 7);

3 to ten początek, a 7 to długość.


1
działa to tylko na „foo_bar”, a nie na „foo_foo_bar”, pytanie dotyczyło ciągu o dowolnej długości, ale o znanym końcu.
Projekt Adrian
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.