Відбиток / фрагмент / обрізка JavaScript від останнього символу в рядку


1973

У мене є струна, 12345.00і я хотів би, щоб вона повернулася 12345.0.

Я подивився trim, але, схоже, це лише обрізка пробілів, і sliceя не бачу, як це буде працювати. Будь-які пропозиції?


36
Ви дбаєте про округлення? 12345.46 = 12345.5 або 12345.4?
RSolberg

9
Чи знаєте ви, що таке суфікс чи хочете розділити та видалити останнє слово на основі підкреслених?
Cᴏʀʏ

65
Хо-хо-хо, @RSolberg: ти не можеш округлити струну!
Ziggy

50
@Ziggy говорить що? Math.round('0.5') === 1;)
TWiStErRob

16
@TWiStErRob О, JavaScript, що я буду робити з вами? * хитає головою *
Чак Ле Батт

Відповіді:


3211

Ви можете використовувати функцію підрядки :

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

Це прийнята відповідь, але відповідно до наведених нижче бесід, синтаксис фрагмента набагато зрозуміліший:

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


23
@Kheu - позначення зрізів для мене набагато чистіші. Раніше я використовував підстрокову версію. Дякую!
Метт Бал

32
пробачте, якщо я помиляюся, але чи не потрібно вам знову присвоювати значення str.substring str? Likestr = str.substring(0, str.length -1);
Doug Molineux

10
Ці sliceта substringметоди все саме те ж саме; крім того, що slice()приймає від'ємний індекс відносно кінця рядка, але не той substring, він видає out-of-boundпомилку
Amol M Kulkarni

20
Якщо хтось цікавиться, substringна 11% швидше, ніж slice. jsperf.com/js-slice-vs-substring-test
BenR

19
substring - це божевільні мікрооптимізації, які, я думаю, не варто робити. Спочатку максимізуйте для читабельності. Потім оптимізуйте низько висячі фрукти, якщо потрібно.
Альфред

1306

Можна використовувати скибочку ! Ви просто повинні переконатися, що знаєте, як ним користуватися. Позитивні # відносно початку, негативні числа відносно кінця.

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

75
Порівняно з прийнятим рішенням, цей спосіб є більш елегантним і його можна використовувати навіть з динамічно створеними струнами
Sameer Alibhai

1
Мені це подобається, тому що він поєднується з php-мисленням для функції substr, простіше запам’ятовувати та писати на льоту.
дорожник

2
@SameerAlibhai Я згоден з вами, але чи не міг цей substringметод використовуватись і в динамічних рядках? Використовуючи str.length, щоб динамічно отримати довжину?
Doug Molineux

Слід додати, що перший індекс включно, а другий ексклюзивний.
Зловмисник

@KevinBeal ви можете просто використовувати F12 в основних браузерах і вводити його в консоль, працює на будь-якій сторінці і навіть у вас є контекст і можуть бути завантажені бібліотеки.
TWiStErRob

263

Ви можете використовувати метод підрядки об’єктів рядка JavaScript:

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

Він безумовно видаляє останні чотири символи з рядка s.

Однак якщо ви хочете умовно видалити останні чотири символи, лише якщо вони точно такі _bar :

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

107
sliceтут краще. s.slice(0, -4)
Тім Даун

12
Як варіант: s.slice (0, - "_ bar" .length) (корисно, якщо не хочеться вводити кількість символів)
Ман

3
Мені це подобається, тому що він також допомагає замінити вказане закінчення.
Майк Граф

162

Найпростіший метод - це використовувати sliceметод рядка, який дозволяє негативні позиції (відповідні зсувам від кінця рядка):

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

Якщо вам потрібно було щось більш загальне, щоб видалити все після (і включаючи) останнього підкреслення, ви можете зробити наступне (до тих пір, sпоки гарантовано буде містити хоча б одну підкреслення):

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


67

Для такої кількості, як ваш приклад, я рекомендую робити це над substring:

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

Зверніть увагу, що це насправді округлене число, хоча, як я вважаю, є бажаним, але, можливо, ні:

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


11
+1 Це те, що потрібно ОП, забудьте помилкове припущення, що є рядки, які слід обрізати.
naugtur

2
Це неправдиве припущення, ОП говорить про рядки. Ваше помилкове припущення, оскільки ОП не говорить про округлення чисел.
Фернандо

30

Використання функції зрізу JavaScript:

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

Це можна використати для видалення '_bar' в кінці рядка будь-якої довжини.


19

Регулярний вираз - це те, що ви шукаєте:

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


Ваше рішення працює, але відповідь Алекса є більш вичерпною. Тож я прийму його. Дякую!
Альберт

1
Це вирішує пов'язану з цим проблему умовного зняття, а не сліпо обрізання
Аарон




7
  1. (. *), фіксує будь-який символ кілька разів

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

  1. ., відповідає останньому символу в даному випадку

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

  1. $, відповідає кінці рядка

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


9
Мені це подобається, оскільки, незважаючи на .splice (), ти знайшов спосіб використовувати регулярний вираз.
QueueHammer

Окрім того, що не знає Unicode, це також не відповідає розривам рядків.
користувач4642212


5

Ось альтернатива, яку я не думаю, що я бачив в інших відповідях, просто заради задоволення.

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

Не настільки розбірливий чи простий, як фрагмент чи підряд, але дозволяє грати з рядком, використовуючи деякі приємні методи масиву, тому варто знати.


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

Якщо ви хочете зробити загальне округлення поплавків, а не просто обрізання останнього символу:

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

EDIT: Здається, що для цього існує вбудована функція, як вказує Паоло. Це рішення, очевидно, набагато чистіше, ніж моє. Використовуйте parseFloat, а потім - toFixed




1

Продуктивність

Сьогодні 2020.05.13 я виконую тести вибраних рішень на Chrome v81.0, Safari v13.1 та Firefox v76.0 на MacOs High Sierra v10.13.6.

Висновки

  • то slice(0,-1)(D) є швидким або самим швидким рішенням для коротких і довгих рядків , і рекомендуються в якості швидкого вирішення кросбраузерності
  • розчини на основі substring(С) таsubstr (Е) швидкі
  • рішення, засновані на регулярних виразах (A, B), повільно / середньо швидко
  • розчини B, F і G повільні для довгих струн
  • рішення F - найповільніше для коротких струн, G - найповільніше для довгих рядків

введіть тут опис зображення

Деталі

Я виконую два тести для розчинів A , B , C , D , E ( ext ), F , G (my)

  • для 8-знакових коротких рядків (від запитання про OP) - ви можете запустити його ТУТ
  • для 1M довгої струни - її можна запустити ТУТ

Рішення представлені у фрагменті нижче

Ось приклади результатів для Chrome для короткого рядка

введіть тут опис зображення


1

Майте на увазі, що String.prototype.{ split, slice, substr, substring }оперувати на UTF-16 рядках, кодованих

Жодна з попередніх відповідей не знає Unicode. У більшості сучасних двигунів JavaScript рядки кодуються як UTF-16, але для вищих точок коду Unicode потрібні сурогатні пари , тому старі, існуючі рядкові методи працюють на кодових блоках UTF-16, а не на кодових точках 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"

Крім того, відповіді RegExp не відповідають розривам рядків наприкінці у своєму поточному вигляді:

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

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


Використовуйте ітератор рядків для ітерації символів

Unicode-відомий код використовує ітератор рядка; бачити Array.fromі ...поширювати . string[Symbol.iterator]можна використовувати (наприклад, замістьstring ).

Також див. Як розділити рядок Unicode на символи в JavaScript .

Приклади:

const string = "ẞ🦊";

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

Використовуйте sі uпрапори на aRegExp

Значок dotAllабо sпрапор створює .символи розриву рядків відповідності, unicodeабо uпрапор включає певні функції, пов'язані з Unicode.

Приклади:

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


Зауважте, що деякі графеми складаються з більш ніж однієї кодової точки, наприклад, 🏳️‍🌈яка складається з послідовності 🏳(U + 1F3F3), VS16(U + FE0F) , ZWJ(U + 200D) , 🌈(U + 1F308). Тут навіть Array.fromрозділимо це на чотири "символи". Поєднання цих можливостей із властивістю Unicode уникає пропозиції властивостей послідовності .


-1

У випадках, коли ви хочете видалити щось, що знаходиться поруч із кінцем рядка (у разі струн змінного розміру), ви можете комбінувати slice () та substr ().

У мене був рядок з розміткою, динамічно побудований, зі списком якорних тегів, розділених комою. Рядок був приблизно таким:

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

Для видалення останньої коми я зробив наступне:

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

-3

Спробуйте це:

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

Ви також можете спробувати робочий приклад на веб-сайті http://jsfiddle.net/informativejavascript/F7WTn/87/ .


3
Дякую kamal Однак я вказав відповідь вище як прийняту для моїх потреб. Помітьте зелену галочку вище. Хоча я перевірив ваш код. :) Тепер у моїй ситуації я знаю лише загальну послідовність символів кінця. Було б краще просто почати перевірку з кінця рядка. Ваша пропозиція не зможе, якщо у мене є рядок, схожий на "foo_b_bar", і я хочу лише вийняти останній "_bar". Дякую, хоча! Цікаво цікаво поставити запитання більше 2 років тому, і все ще отримувати відповіді на нього сьогодні. :)
Альберт

-4

@Jason S:

Можна використовувати скибочку! Ви просто повинні переконатися, що знаєте, як ним користуватися. Позитивні # відносно початку, негативні числа відносно кінця.

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

Вибачте за мою графікоману, але повідомлення було позначено "jquery" раніше. Тому, ви не можете використовувати slice () всередині jQuery, оскільки slice () - метод jQuery для операцій з елементами DOM, а не підрядками ... Іншими словами, відповідь @Jon Erickson пропонує дійсно ідеальне рішення.

Однак ваш метод працюватиме з функції jQuery всередині простого Javascript. Потрібно сказати через останнє обговорення в коментарях, що jQuery набагато частіше поновлюється розширення JS, ніж найвідоміший його власний батько ECMAScript.

Тут також існують два методи:

як наші:

string.substring(from,to) як плюс, якщо 'до' індекс нульовий повертає решту рядка. тому: string.substring(from) позитивні чи негативні ...

та деякі інші - substr (), які забезпечують діапазон підрядків та "довжина", можуть бути лише позитивними: string.substr(start,length)

Також деякі технічні працівники вважають, що останній метод string.substr(start,length)не працює або не працює з помилками для MSIE.


3
Що ви маєте на увазі? String.prototype.sliceє рідним методом
naugtur

це лише те, що ти сказав. Народний метод Javascript, але також slice()метод jQuery для маніпуляції з DOM: jQuery API: .slice () . І Впевнено, що це МОЖЕ бути представленим як поліморфне успадкування JS Array.slice (), але це два різні способи, і я думаю, що це потрібно розрізнити. Тож це лише наближення до цих знань.
стрімкий

12
Якщо ви зателефонуєте .sliceна змінну, яка є рядком, вона зробить саме те, що хотіла ОП. Не має значення, чи він знаходиться "всередині jQuery", і немає ніякого способу "заважати" будь-яким чином, якщо ви не перезапишете String.prototypejQuery, що, я впевнений, перешкоджатиме роботі будь-якого коду JavaScript. Ваша відповідь просто говорить, що інша відповідь не є доброю, і аргумент, який ви наводите, невірний.
naugtur

1
Я можу погодитися з @naugtur, що ця відповідь неправильна, метод зрізу рядка не здійснюється jQuery.
рекобат

1
Думаю, що наугтур робив саме те, що, можливо, ви можете закінчити рядок, обгорнутий об’єктом jQuery (наприклад, якщо ви зробите якісь фантазійні .dataманіпуляції і закінчитеся цією "рядкою"), яка, якщо ви зателефонували sliceна неї, не робив би того, що хочеш. Однак це не дуже корисна відповідь.
mAAdhaTTah

-8

Використовуйте підрядку, щоб отримати все ліворуч від _bar. Але спочатку потрібно отримати instr _bar у рядку:

str.substring(3, 7);

3 - це початок, а 7 - довжина.


1
це працює лише на "foo_bar", а не на "foo_foo_bar", питання стосувалося рядка будь-якої довжини, але відомий кінець.
Дизайн Адріана
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.