2011-04-07 22 views
21

Me gustaría dividir una cadena solo en las primeras n ocurrencias de un delimitador. Lo sé, podría agregarlos usando un ciclo, pero ¿no hay un enfoque más directo?Dividir una cadena solo en las primeras n ocurrencias de un delimitador

var string = 'Split this, but not this';  
var result = new Array('Split', 'this,', 'but not this'); 
+0

ver a mi última edición, creo que su exactamente lo que busca fo r. – clamchoda

+0

Posible duplicado de [cadena dividida solo en la primera instancia del carácter especificado] (https://stackoverflow.com/questions/4607745/split-string-only-on-first-instance-of-specified-character) – Keelan

Respuesta

5

El JavaScript ".split()" función ya acepta un segundo parámetro que indica el número máximo de divisiones a realizar. Sin embargo, no retiene el final de la cadena original; tendrías que volver a pegarlo.

Otro enfoque sería raspar iterativamente una parte principal de la cuerda con una expresión regular, deteniéndose cuando haya alcanzado su límite.

var str = "hello out there cruel world"; 
var parts = []; 
while (parts.length < 3) { // "3" is just an example 
    str = str.replace(/^(\w+)\s*(.*)$/, function(_, word, remainder) { 
    parts.push(word); 
    return remainder; 
    }); 
} 
parts.push(str); 

edición — y que sólo se me ocurre que otra forma sencilla sería utilizar simplemente ".split()", arrancar las primeras partes, y luego simplemente ".slice()" y "unir()" al resto.

+0

En realidad, no . Regresaría '[" Dividir "," esto "," pero "]', no lo que él pidió. El límite en 'split' es sorprendentemente inútil y, a diferencia de muchas otras funciones' split'. –

+1

Sí @TJ es por eso que agregué la advertencia sobre volver a pegar la "cola". – Pointy

+2

No estaba allí cuando comencé hace unos momentos. :-) Espera, tal vez fue. –

2

Aunque puede dar split un límite, no recibirá lo que dijo que desea. Por desgracia, tendrá que rodar su propia sobre esto, por ejemplo .:

var string = 'Split this, but not this'; 
var result = string.split(' '); 

if (result.length > 3) { 
    result[2] = result.slice(2).join(' '); 
    result.length = 3; 
} 

Pero incluso entonces, se termina la modificación del número de plazas en las últimas partes de la misma. Así que probablemente me acaba de hacerlo de la manera antigua de escritura-su-propio-loop:

function splitWithLimit(str, delim, limit) { 
    var index, 
     lastIndex = 0, 
     rv = []; 

    while (--limit && (index = str.indexOf(delim, lastIndex)) >= 0) { 
    rv.push(str.substring(lastIndex, index)); 
    lastIndex = index + delim.length; 
    } 
    if (lastIndex < str.length) { 
    rv.push(str.substring(lastIndex)); 
    } 
    return rv; 
} 

Live copy

30

Según MDN:

string.split(separator, limit); 

Actualización:

var string = 'Split this, but not this', 
    arr = string.split(' '), 
    result = arr.slice(0,2); 

result.push(arr.slice(2).join(' ')); // ["Split", "this,", "but not this"] 

Actualización de la versión 2 (uno slice más corto):

var string = 'Split this, but not this', 
    arr = string.split(' '), 
    result = arr.splice(0,2); 

result.push(arr.join(' ')); // result is ["Split", "this,", "but not this"] 
+2

Esto eliminará la tercera parte. – nines

+1

Hola, davin. Tu respuesta me ayudó. ¿Qué piensas sobre: ​​'var string = 'Dividir esto, pero no esto', result = string.split (''), result.push (result.splice (2) .join (''));'? – Jayen

+0

Aunque conciso, esto no soluciona el caso en el que la cadena solo tiene un espacio: la matriz de resultados contendrá una cadena vacía adicional. – riv

3

Para este propósito puede utilizar de Split (delimitador) y elija un delimitador.

var testSplit = "Split this, but not this"; 
var testParts= testSplit.Split(","); 

var firstPart = testParts[1]; 

// firstPart = "Split this" 

No 100% en mi sintaxis No he usado Javascript en bastante tiempo. Pero sé que así es como se hace ...

EDITAR ** Lo siento, mi error. Ahora creo que sé lo que preguntas y creo que la forma más fácil de hacerlo es usar substr. Muy fácil, no se requieren bucles. Acaba de hacer un ejemplo, funciona perfecto

// so first, we want to get everything from 0 - the first occurence of the comma. 
// next, we want to get everything after the first occurence of the comma. (if you only define one parameter, substr will take everything after that parameter. 

var testString = "Split this, but this part, and this part are one string"; 
var part1 = testString.substr(0,testString.indexOf(',')); 
var part2 = testString.substr(testString.indexOf(',')); 

//part1 = "Split this" 
//part2= "but this part, and this part are one string" 
+0

En este ejemplo, funcionaría, pero en realidad podría haber más apariciones de comas, etc. después. – nines

+0

@nines ¿Pero no es esto lo que estás tratando de hacer? "solo en las primeras n apariciones de un delimitador" – clamchoda

+0

Mi ejemplo ha sido estúpido, lo siento. En realidad, tengo un tipo de protocolo simple: 'comando + delimitador + opciones + delimitador + datos'. Las dos primeras partes son fijas, por lo que no habrá un personaje, pero la parte de datos es de longitud variable y podría contener cualquier cosa. Simplemente pensé que habría una forma estándar corta de hacer esto, ya que la división de JavaScript parece ser diferente de otros lenguajes que cortan el resto en lugar de ponerlo en otro elemento. – nines

0
var s='Split this, but not this', a=s.split(','), b=a[0].split(' '); 
b.push(a[1]); 
alert(b); 

alertas [ 'Split', 'esto' 'pero esto no']

14

utiliza matriz.rebanada:

function splitWithTail(str,delim,count){ 
    var parts = str.split(delim); 
    var tail = parts.slice(count).join(delim); 
    var result = parts.slice(0,count); 
    result.push(tail); 
    return result; 
} 

Resultados:

splitWithTail(string," ",2) 
// => ["Split", "this,", "but not this"] 
1

Hola allí tuve el mismo problema quería dividir sólo varias veces, no podía encontrar nada y por eso sólo extendió el DOM - sólo una solución rápida y sucia, pero funciona :)

String.prototype.split = function(seperator,limit) { 
    var value = ""; 
    var hops = []; 

    // Validate limit 
    limit = typeof(limit)==='number'?limit:0; 

    // Join back given value 
    for (var i = 0; i < this.length; i++) { value += this[i]; } 

    // Walkthrough given hops 
    for (var i = 0; i < limit; i++) { 
     var pos = value.indexOf(seperator); 
     if (pos != -1) { 
      hops.push(value.slice(0,pos)); 
      value = value.slice(pos + seperator.length,value.length) 

     // Done here break dat 
     } else { 
      break; 
     } 
    } 
    // Add non processed rest and return 
    hops.push(value) 
    return hops; 
} 

En su caso se vería que

>>> "Split this, but not this".split(' ',2) 
["Split", "this,", "but not this"] 
1

versión mejorada de un cuerdo limit aplicación con el soporte adecuado RegEx:

function splitWithTail(value, separator, limit) { 
    var pattern, startIndex, m, parts = []; 

    if(!limit) { 
     return value.split(separator); 
    } 

    if(separator instanceof RegExp) { 
     pattern = new RegExp(separator.source, 'g' + (separator.ignoreCase ? 'i' : '') + (separator.multiline ? 'm' : '')); 
    } else { 
     pattern = new RegExp(separator.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1'), 'g'); 
    } 

    do { 
     startIndex = pattern.lastIndex; 
     if(m = pattern.exec(value)) { 
      parts.push(value.substr(startIndex, m.index - startIndex)); 
     } 
    } while(m && parts.length < limit - 1); 
    parts.push(value.substr(pattern.lastIndex)); 

    return parts; 
} 

Ejemplo de uso:

splitWithTail("foo, bar, baz", /,\s+/, 2); // -> ["foo", "bar, baz"] 

Construido para & probado en Chrome, Firefox, Safari, Internet Explorer 8 +.

0

Sin embargo, otra aplicación que acabo de escribir:

export function split(subject, separator, limit=undefined, pad=undefined) { 
    if(!limit) { 
     return subject.split(separator); 
    } 
    if(limit < 0) { 
     throw new Error(`limit must be non-negative`); 
    } 
    let result = []; 
    let fromIndex = 0; 
    for(let i=1; i<limit; ++i) { 
     let sepIdx = subject.indexOf(separator, fromIndex); 
     if(sepIdx < 0) { 
      break; 
     } 
     let substr = subject.slice(fromIndex, sepIdx); 
     result.push(substr); 
     fromIndex = sepIdx + separator.length; 
    } 
    result.push(subject.slice(fromIndex)); 
    while(result.length < limit) { 
     result.push(pad); 
    } 
    return result; 
} 

No usa expresiones regulares, ni exceso de dividir y volver a unirse.

Esta versión garantiza exactamente limit elementos (almohadilla con undefined s si no hay suficientes separadores); esto hace que sea seguro para hacer este tipo de cosas ES6:

let [a,b,c] = split('a$b','$',3,null); 
// a = 'a', b = 'b', c = null 
2
var result = [string.split(' ',1).toString(), string.split(' ').slice(1).join(' ')]; 

Resultados: en

["Split", "this, but not this"] 
0

me gusta usar shift.

function splitFirstN(str,n,delim){ 
    var parts = str.split(delim); 
    var r = []; 
    for(var i = 0; i < n; i++){ 
     r.push(parts.shift()); 
    } 
    r.push(parts.join(delim)); 
    return r; 
} 

var str = 'Split this, but not this';  
var result = splitFirstN(str,2,' '); 
0

Combinación de split y join con características ES6 hace esto con buena pinta:

let [str1, str2, ...str3] = string.split(' '); 
str3 = str3.join(' '); 
0

Nada una expresión regular simple no puede hacer:

const string = 'Split this, but not this'; 
 
console.log(string.match(/^(\S+)\s*(\S+)?\s*([\s\S]+)?$/).slice(1));

0

En mi caso lo estaba intentando para analizar gt grep stdout. Así que tenía un {filename}: {linenumber}: {context}. No me gusta dividirme y luego unirme. Deberíamos ser capaces de analizar la cadena una vez. Simplemente podría pasar por cada letra y dividir en los dos primeros dos puntos. Una forma más rápida de hacerlo de la caja es mediante el uso del método de coincidencia y regex.

Por lo tanto,

txt.match(/(.+):(\d+):(.*)/)

Funciona muy bien

0

Sin embargo, otra aplicación con un límite;

// takes string input only 
function split(input, separator, limit) { 
    input = input.split(separator); 
    if (limit) { 
     input = input.slice(0, limit - 1).concat(input.slice(limit - 1).join(separator)); 
    } 
    return input; 
} 
0

Mi versión, universal, admite delimitadores RegExp y no RegExp. Muy optimizado Pruebas provistas. Por qué: ya que otras versiones de RegExp están llenas de errores y esta no es una función trivial.

uso:

"a b c d".split_with_tail(/ +/,3) = ['a','b','c d'] 
"a b c d".split_with_tail(' ',3) = ['a','b',' c d'] 

Código

String.prototype.split_with_tail = function(delimiter,limit) 
{ 
    if(typeof(limit) !== 'number' || limit < 1) return this.split(delimiter,limit); 

    var parts = this.split(delimiter,limit+1); 
    if(parts.length <= limit) return parts; 
    parts.splice(-2,2); 

    limit = Math.floor(limit) - 1; // used later as index, speed optimization; limit can be float .. 
    if(delimiter instanceof RegExp) { 
     // adds 'g' flag to any regexp: 
     delimiter += ''; 
     var len = delimiter.lastIndexOf('/'); 
     delimiter = new RegExp(delimiter.slice(1, len), delimiter.slice(len + 1)+'g'); 

     len = 0; 
     while(limit--) len += parts[limit].length + (delimiter.exec(this))[0].length; 
    } 
    else { 
     var len = limit * (''+delimiter).length; 
     while(limit--) len += parts[limit].length; 
    } 

    parts.push(this.substring(len)); // adds tail, finally 
    return parts; 
} 

pruebas

function test(str,delimiter,limit,result) { 
    if(JSON.stringify(result) !== JSON.stringify(str.split_with_tail(delimiter,limit))) { 
     console.log(arguments); 
     console.log(str.split_with_tail(delimiter,limit)); 
     throw "lol"; 
    } 
} 
test('',/ +/,undefined,['']); 
test('',/ +/,3,['']); 
test('a',/ +/,0.1,[]); 
test('a',/ +/,1,['a']); 
test('a a',/ +/,1,['a a']); 
test('a a',/ +/,2.1,['a','a']); 
test('a a a',/ +/,2.9,['a','a a']); 
test('aaaaa aa a',/ +/,1,['aaaaa aa a']); 
test('aaaaa aa a',/ +/,2,['aaaaa', 'aa a']); 
test('a a',/ +/,2,['a','a']); 
test('a',/ +/,3,['a']); 
test('a a',/ +/,3,['a','a']); 
test('a a a',/ +/,3,['a','a','a']); 
test('a a a a',/ +/,3,['a','a','a a']); 
test('a a a a',/ +/,4,['a','a','a','a']); 
test('a aa aaa ',/ +/,4,['a','aa','aaa','']); 
test('a a a a',/ +/,2,['a','a a a']); 
test('a a a a',/ +/,1,['a a a a']); 
test('a a a a',/ +/,0,[]); 
test('a a a a',/ +/,undefined,['a','a','a','a']); 
test('a a a a',/ +/,-1,['a','a','a','a']); 

test('a',' ',3,['a']); 
test('aaaaa aa a',' ',2,['aaaaa', 'aa a']); 
test('aaaaa aa a',' ',2,['aaaaa','aa a']); 
test('a a a',' ',3,['a','a','a']); 
test('a a a a',' ',3,['a','a','a a']); 
test('a a a a',' ',3,['a','a',' a a']); 
test('a a a a',' ',2,['a','a a a']); 
test('a a a a',' ',1,['a a a a']); 
test('a a a a',' ',0,[]); 
test('a a a a',' ',undefined,['a','a','','a','a']); 
test('a a a a',' ',-1,['a','a','','a','a']); 
test('1232425',2,3,['1','3','425']); 
console.log("good!"); 
Cuestiones relacionadas