Розділити рядок один раз у javascript?


82

Як я можу розділити рядок лише один раз, тобто зробити 1|Ceci n'est pas une pipe: | Ouiсинтаксичний розбір на ["1", "Ceci n'est pas une pipe: | Oui"]:?

Здається, межа розділення не допомагає ...

Відповіді:


79

Це не дуже гарний підхід, але працює з гідною ефективністю:

var string = "1|Ceci n'est pas une pipe: | Oui";
var components = string.split('|');
alert([components.shift(), components.join('|')]​);​​​​​

Ось коротка демонстрація цього


Я думаю, це насправді краще, ніж регулярний вираз. Вибрано як правильно, дякую!
Ставрос Корокітакіс,

2
Щоб пояснити, він ділиться на N частин, а потім виводить першу на список і приєднує решту до того ж списку.
Ставрос Корокітакіс,

Якщо ви хочете витягнути з маркера k токенів замість 1, виконайте те саме, що вище, за винятком того, що використовуєте компоненти.splice (0, k) замість components.shift ().
D Coetzee

Для тих, хто задається питанням, як це зробити з 2 або більше патронами, ви можете скористатися shift in loop або:components.splice(0,2).slice(0,2)
Ultimater

114

Ви хочете використовувати, String.indexOf('|')щоб отримати індекс першого входження '|'.

var i = s.indexOf('|');
var splits = [s.slice(0,i), s.slice(i+1)];

18
Не так "весело", як у Ніка, але, мабуть, ефективніше. Також зверніть увагу, що +1насправді має бути довжина рядка-роздільника, якщо більше одного символу.
devios1 02

Чому це рішення менш "веселе"?
Bentley4,

Для тих, хто цікавиться, щоб зробити це з 2 або більше шматками, ви можете використовувати indexOf у циклі або:var i = s.split('|',2).join('|').length;//2nd index var splits = [s.slice(0,i).split('|'), s.slice(i+1)];
Ultimater

6
Це НЕ працює як split, коли IndexOf повертає -1 (Наприклад, якщо var s = 'string', це поверне ['strin', 'string']). Вам довелося б писати умовний.
JJJ,

14

Ви можете використовувати:

var splits = str.match(/([^|]*)\|(.*)/);
splits.shift();

Регулярний вираз розділяє рядок на дві групи, що збігаються (у дужках), текст перед першою | а текст після. Потім ми shiftотримали результат, щоб позбутися цілого рядкового збігу ( splits[0]).


1
належним чином, це, мабуть, має закріпитися на початку. однак регулярні вирази javascript здаються жадібними.
muhmuhten

6

один лайнер та imo, простіше:

var str = 'I | am super | cool | yea!';
str.split('|').slice(1).join('|');

Це повертає "я супер | круто | так!"


4
Це не те, про що просили, вони також шукають зниклу першу частину.
SmujMaiku

6

Синтаксис ES6 допускає інший підхід:

function splitOnce(s, on) {
   [first, ...rest] = s.split(on)
   return [first, rest.length > 0? rest.join(on) : null]
}

Який також обробляє випадковість рядка, який не має |шляхом повернення null, а не порожнього рядка, що є більш явним.

splitOnce("1|Ceci n'est pas une pipe: | Oui", "|")
>>> ["1", "Ceci n'est pas une pipe: | Oui"]

splitOnce("Celui-ci n'a pas de pipe symbol!", "|")
>>> ["Celui-ci n'a pas de pipe symbol!", null]

Pas de pipe? C'est null!

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


3

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

function splitOnce(input, splitBy) {
    var fullSplit = input.split(splitBy);
    var retVal = [];
    retVal.push( fullSplit.shift() );
    retVal.push( fullSplit.join( splitBy ) );
    return retVal;
}

var whatever = splitOnce("1|Ceci n'est pas une pipe: | Oui", '|');

3

Якщо рядок не містить роздільника, рішення NickCraver все одно поверне масив із двох елементів, другий - порожній рядок. Я віддаю перевагу поведінці, яка відповідає поведінці розколу. Тобто, якщо вхідний рядок не містить роздільника, повертається лише масив з одним елементом.

var splitOnce = function(str, delim) {
    var components = str.split(delim);
    var result = [components.shift()];
    if(components.length) {
        result.push(components.join(delim));
    }
    return result;
};

splitOnce("a b c d", " "); // ["a", "b c d"]
splitOnce("a", " "); // ["a"]

1

Так само зле, як і більшість відповідей на даний момент:

var splits = str.split('|');
splits.splice(1, splits.length - 1, splits.slice(1).join('|'));

0

Альтернативний, короткий підхід, крім товарних в інших місцях, полягає у використанні replace()обмеження на вашу користь.

var str = "1|Ceci n'est pas une pipe: | Oui";
str.replace("|", "aUniquePhraseToSaySplitMe").split("aUniquePhraseToSaySplitMe");

Як зазначає @sreservoir у коментарях, унікальна фраза повинна бути по-справжньому унікальною - вона не може бути у джерелі, на яке ви запускаєте цей розкол, або ви отримаєте рядок, розділений на більше частин, ніж хочете. Недрукований символ, як він каже, може зробити, якщо ви запускаєте це проти вводу користувача (тобто, введеного в браузері).


це працює лише в тому випадку, якщо „унікальна” фраза неможлива для заповнення. якщо читання з текстового файлу, це неможливо. при читанні з браузера - будь-який недрукований керуючий символ, якщо, мабуть, добре. вкладка теж творить чудеса. у будь-якому випадку, "aUniquePhraseToSaySplitMe" майже напевно, можливо, є частиною вхідних даних, і тому є небезпечним.
muhmuhten

Ви, звичайно, праві. Мій приклад - це лише приклад, який має на меті пояснити, що робиться стисло. Я включу вашу думку в саму відповідь. Дякую!

Якщо ви використовуєте str для своєї унікальної фрази, ви знаєте, що вона не може бути там знову! : злий усміх
Фабіо Белтраміні

0

Це трохи довше, але це працює так, як я вважаю, обмеження повинно:

function split_limit(inString, separator, limit){
    var ary = inString.split(separator);
    var aryOut = ary.slice(0, limit - 1);
    if(ary[limit - 1]){
        aryOut.push(ary.slice(limit - 1).join(separator));
    }
    return aryOut;
}
console.log(split_limit("1|Ceci n'est pas une pipe: | Oui","|", 1));
console.log(split_limit("1|Ceci n'est pas une pipe: | Oui","|", 2));
console.log(split_limit("1|Ceci n'est pas une pipe: | Oui","|", 3));
console.log(split_limit("1|Ceci n'est pas une pipe: | Oui","|", 7));

https://jsfiddle.net/2gyxuo2j/

limit Zero повертає кумедні результати, але в ім'я ефективності я залишив перевірку на це. Ви можете додати це як перший рядок функції, якщо вам це потрібно:

if(limit < 1) return [];

0

якщо ви хочете використовувати "трубопровід", reduceце ваш друг

const separator = '|'
jsonNode.split(separator)
   .reduce((previous, current, index) =>
    {
        if (index < 2) previous.push(current)
        else previous[1] += `${separator}${current}`
        return previous
    }, [])
    .map((item: string) => (item.trim()))
    .filter((item: string) => (item != ''))


-1

використовуйте функціональність регулярного виразу javascript і візьміть перший захоплений вираз.

RE, мабуть, виглядав би так /^([^|]*)\|/.

насправді, це потрібно лише в тому /[^|]*/випадку, якщо ви підтвердили, що рядок відформатований таким чином, через жадібність регулярних виразів JavaScript.

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