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?

Phill Pafford
źródło
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);

Jon Erickson
źródło
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
Jason S.
źródło
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, "");
Alex Martelli
źródło
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);

Tim Down
źródło
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));

Paolo Bergantino
źródło
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.

Akshay Joshi
źródło
19

Wyrażenie regularne jest tym, czego szukasz:

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

w35l3y
źródło
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
10

Spróbuj tego:

const myString = "Hello World!";
console.log(myString.slice(0, -1));

Somwang Souksavatd
źródło
9

Co powiesz na:

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

dariom
źródło
9

Użyj wyrażenia regularnego:

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

Marc477
źródło
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]);

strony
źródło
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
6

const str = "test!";
console.log(str.slice(0, -1));

dota2pro
źródło
3
Co to dodaje, w porównaniu do wszystkich innych odpowiedzi?
Dan Dascalescu
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ć.

Mark Walters
źródło
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
uofc
źródło
4

Najkrótsza droga:

str.slice(0, -1); 
Idan
źródło
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

PatrikAkerstrand
źródło
1
if(str.substring(str.length - 4) == "_bar")
{
    str = str.substring(0, str.length - 4);
}
Matthew Flaschen
źródło
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

Kamil Kiełczewski
źródło
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 .

użytkownik4642212
źródło
-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);
bestafubana
źródło
-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/ .

kamal
źródło
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.

szybki
źródło
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ść.

ryczy
źródło
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