¿Dividir cadena una vez en javascript?


82

¿Cómo puedo dividir una cadena solo una vez, es decir, hacer un 1|Ceci n'est pas une pipe: | Ouianálisis de ["1", "Ceci n'est pas une pipe: | Oui"]:?

El límite en split no parece ayudar ...

Respuestas:


77

Este no es un enfoque agradable, pero funciona con una eficiencia decente:

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

Aquí hay una demostración rápida


En realidad, esto es mejor que la expresión regular, creo. Seleccionado como correcto, ¡gracias!
Stavros Korokithakis

2
Para aclarar, se divide en N partes, luego aparece la primera en una lista y se une al resto en la misma lista.
Stavros Korokithakis

Si desea obtener k tokens de la cadena en lugar de 1, haga lo mismo que antes, excepto que use components.splice (0, k) en lugar de components.shift ().
D Coetzee

Para aquellos que se preguntan cómo hacer esto con 2 o más mandriles, puede usar shift in a loop o:components.splice(0,2).slice(0,2)
Ultimater

113

Desearía usar String.indexOf('|')para obtener el índice de la primera aparición de '|'.

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

18
No tan "divertido" como el de Nick, pero probablemente más eficiente. También tenga en cuenta +1que en realidad debería ser la longitud de la cadena de separación, si tiene más de un carácter.
devios1

¿Por qué esta solución es menos "divertida"?
Bentley 4

Para los que preguntan, para hacer esto con 2 o más trozos, se puede usar indexOf en un bucle o:var i = s.split('|',2).join('|').length;//2nd index var splits = [s.slice(0,i).split('|'), s.slice(i+1)];
Ultimater

6
Esto NO funciona como split cuando IndexOf devuelve -1 (por ejemplo, si var s = 'string' devolvería ['strin', 'string']). Tendrías que escribir un condicional.
JJJ

14

Puedes usar:

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

La expresión regular divide la cadena en dos grupos coincidentes (entre paréntesis), el texto que precede al primero | y el texto siguiente. Luego, obtenemos shiftel resultado para deshacernos de toda la cadena match ( splits[0]).


1
correctamente, eso probablemente debería anclar al principio. sin embargo, javascript regexen parece ser codicioso.
muhmuhten

6

un trazador de líneas y en mi opinión, más simple:

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

Esto devuelve "soy super | genial | yea!"


3
Esto no es lo que se pidió, también están buscando la primera parte que falta.
SmujMaiku

5

La sintaxis de ES6 permite un enfoque diferente:

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

Lo que también maneja la eventualidad de que la cadena no tenga un |retorno nulo en lugar de una cadena vacía, que es más explícita.

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!

Agregué esta respuesta principalmente para poder hacer un juego de palabras con el símbolo de la tubería, pero también para mostrar la sintaxis de es6: es sorprendente cuántas personas todavía no lo usan ...


3

Prueba esto:

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

Si la cadena no contiene el delimitador, la solución de @ NickCraver aún devolverá una matriz de dos elementos, siendo el segundo una cadena vacía. Prefiero que el comportamiento coincida con el de la división. Es decir, si la cadena de entrada no contiene el delimitador, devuelve solo una matriz con un solo elemento.

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

Tan malvado como la mayoría de las respuestas hasta ahora:

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

0

Un enfoque alternativo y corto, además de los de bienes en otros lugares, es utilizar replace()el límite a su favor.

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

Como señala @sreservoir en los comentarios, la frase única debe ser verdaderamente única: no puede estar en la fuente sobre la que está ejecutando esta división, o la cadena se dividirá en más partes de las que desea. Un carácter no imprimible, como él dice, puede funcionar si está ejecutando esto contra la entrada del usuario (es decir, escrito en un navegador).


eso solo funciona si la frase 'única' es indiscutible. si lee de un archivo de texto, esto es imposible. si lee desde el navegador, cualquier carácter de control no imprimible si probablemente está bien. pestaña también funciona de maravilla. en cualquier caso, "aUniquePhraseToSaySplitMe" es casi definitivamente posiblemente parte de la entrada y, por lo tanto, es peligroso.
muhmuhten

Estás en lo cierto, por supuesto. Mi ejemplo es solo un ejemplo con miras a explicar lo que se está haciendo de manera concisa. Incorporaré su punto en la respuesta misma. ¡Gracias!

Si usa str para su frase única, ¡sabrá que no puede volver a estar allí! : sonrisa malvada
Fabio Beltramini

0

Este es un poco más largo, pero funciona como creo que el límite debería:

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 of Zero devuelve resultados divertidos, pero en nombre de la eficiencia, dejé el cheque. Puede agregar esto como la primera línea de la función si lo necesita:

if(limit < 1) return [];

0

si quieres utilizar una "canalización", ¿ reducees tu amigo?

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 != ''))

0

Método más eficaz:

const str = "1|Ceci n'est pas une pipe: | Oui"

const [head] = str.split('|', 1);

const result = [head, str.substr(head.length + 1)]

console.log(result);


-1

use la funcionalidad de expresión regular de JavaScript y tome la primera expresión capturada.

el RE probablemente se vería así /^([^|]*)\|/.

en realidad, solo necesita /[^|]*/si ha validado que la cadena está formateada de tal manera, debido a la codicia de las expresiones regulares de JavaScript.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.