Chaîne divisée sur la première occurrence d'espace blanc

150

Je n'ai pas obtenu une expression régulière optimisée qui m'a divisé une chaîne en se basant sur la première occurrence d'espace blanc:

var str="72 tocirah sneab";

J'ai besoin d'avoir:

[
    "72",
    "tocirah sneab",
]
Luca
la source
1
Qu'entendez-vous par «optimisé»? Est - ce qu'il a d'être une expression régulière?
Deestan
Veuillez prendre le temps de faire défiler jusqu'à la réponse de @ georg - beautiful stackoverflow.com/a/10272828/93910
Sanjay Manohar

Réponses:

324

Si vous ne vous souciez que du caractère d'espace (et non des tabulations ou d'autres caractères d'espacement) et que vous ne vous souciez que de tout avant le premier espace et de tout après le premier espace, vous pouvez le faire sans une expression régulière comme celle-ci:

str.substr(0,str.indexOf(' ')); // "72"
str.substr(str.indexOf(' ')+1); // "tocirah sneab"

Notez que s'il n'y a pas d'espace du tout, la première ligne renverra une chaîne vide et la deuxième ligne renverra la chaîne entière. Assurez-vous que c'est le comportement que vous souhaitez dans cette situation (ou que cette situation ne se produira pas).

Trott
la source
50

Javascript ne prend pas en charge les lookbehinds, ce splitn'est donc pas possible. matchtravaux:

str.match(/^(\S+)\s(.*)/).slice(1)

Une autre astuce:

str.replace(/\s+/, '\x01').split('\x01')

que diriez-vous:

[str.replace(/\s.*/, ''), str.replace(/\S+\s/, '')]

et pourquoi pas

reverse = function (s) { return s.split('').reverse().join('') }
reverse(str).split(/\s(?=\S+$)/).reverse().map(reverse)

ou peut-être

re = /^\S+\s|.*/g;
[].concat.call(re.exec(str), re.exec(str))

Mise à jour 2019 : à partir de l'ES2018, les lookbehinds sont pris en charge:

str = "72 tocirah sneab"
s = str.split(/(?<=^\S+)\s/)
console.log(s)

Georg
la source
str.match(/^(\S+)\s(.*)/).slice(1) ne fonctionnera pas pour une chaîne qui n'a pas d'espace
Junaid
30

Dans ES6, vous pouvez également

let [first, ...second] = str.split(" ")
second = second.join(" ")
user1652176
la source
2
J'ai beaucoup aimé cela et cela fonctionne bien, mais en termes de performances, c'est plutôt mauvais pour la solution de "sous-chaîne" la plus votée. je viens de le tester et c'est environ 10 fois plus lent.
pootzko
19

Tard dans le jeu, je sais mais il semble y avoir un moyen très simple de le faire:

const str = "72 tocirah sneab";
const arr = str.split(/ (.*)/);
console.log(arr);

Cela partira arr[0]avec "72"et arr[1]avec "tocirah sneab". Notez que arr [2] sera vide, mais vous pouvez simplement l'ignorer.

Pour référence:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split#Capturing_parentheses

Cliff Stanford
la source
Notez que cela produit un dernier élément vide.
Benjamin Intal le
13
var arr = [];             //new storage
str = str.split(' ');     //split by spaces
arr.push(str.shift());    //add the number
arr.push(str.join(' '));  //and the rest of the string

//arr is now:
["72","tocirah sneab"];

mais je pense toujours qu'il existe un moyen plus rapide.

Joseph
la source
11

La solution de georg est agréable, mais se casse si la chaîne ne contient aucun espace. Si vos chaînes ont une chance de ne pas contenir d'espaces, il est plus sûr d'utiliser .split et de capturer des groupes comme ceci:

str_1 = str.split(/\s(.+)/)[0];  //everything before the first space
str_2 = str.split(/\s(.+)/)[1];  //everything after the first space
fpscoline
la source
9

Vous pouvez également utiliser .replace pour remplacer uniquement la première occurrence,

str = str.replace(' ','<br />');

En laissant de côté le / g.

DEMO

Dédale
la source
3
@DannyHerran .. Non, non? Avez-vous même testé le code? Il n'y a pas de modificateur / g. Ce n'est pas mondial. Essayez de tester le code avant de prétendre savoir ce qu'il fait . Testé également dans les trois principaux navigateurs. J'aimerais savoir pourquoi vous pensez ce que vous faites.
Daedalus du
C'est intelligent parce que j'ai toujours considéré cela comme un défaut. C'est la première fois que je vois que cela est profité de :)
Gogol
2

Divisez simplement la chaîne en un tableau et collez les parties dont vous avez besoin ensemble. Cette approche est très flexible, elle fonctionne dans de nombreuses situations et il est facile de raisonner. De plus, vous n'avez besoin que d'un seul appel de fonction.

arr = str.split(' ');             // ["72", "tocirah", "sneab"]
strA = arr[0];                    // "72"
strB = arr[1] + ' ' + arr[2];     // "tocirah sneab"

Alternativement, si vous voulez choisir ce dont vous avez besoin directement à partir de la chaîne, vous pouvez faire quelque chose comme ceci:

strA = str.split(' ')[0];                    // "72";
strB = str.slice(strA.length + 1);           // "tocirah sneab"

Ou comme ça:

strA = str.split(' ')[0];                    // "72";
strB = str.split(' ').splice(1).join(' ');   // "tocirah sneab"

Cependant, je suggère le premier exemple.

Démo de travail: jsbin

Rotareti
la source
Comme ça! Avez-vous des «inconvénients»?
iglesiasedd
0

Chaque fois que j'ai besoin d'obtenir une classe à partir d'une liste de classes ou d'une partie d'un nom de classe ou d'un identifiant, j'utilise toujours split () puis je l'obtiens spécifiquement avec l'index du tableau ou, le plus souvent dans mon cas, pop () pour obtenir le dernier élément ou shift () pour obtenir le premier.

Cet exemple récupère les classes du div "gallery_148 ui-sortable" et renvoie l'ID de galerie 148.

var galleryClass = $(this).parent().prop("class"); // = gallery_148 ui-sortable
var galleryID = galleryClass.split(" ").shift(); // = gallery_148
galleryID = galleryID.split("_").pop(); // = 148
//or
galleryID = galleryID.substring(8); // = 148 also, but less versatile 

Je suis sûr qu'il pourrait être compacté en moins de lignes, mais je l'ai laissé élargi pour plus de lisibilité.

acarito
la source
0

J'avais besoin d'un résultat légèrement différent.

Je voulais le premier mot, et ce qui est venu après - même s'il était vide.

str.substr(0, text.indexOf(' ') == -1 ? text.length : text.indexOf(' '));
str.substr(text.indexOf(' ') == -1 ? text.length : text.indexOf(' ') + 1);

donc si l'entrée est onewordvous obtenez onewordet ''.

Si l'entrée est, one word and some morevous obtenez oneet word and some more.

Jim Richards
la source
0

Je ne sais pas pourquoi toutes les autres réponses sont si compliquées, alors que vous pouvez tout faire en une seule ligne, en gérant également le manque d'espace.

À titre d'exemple, obtenons le premier et les "autres" composants d'un nom:

let [first, last] = 'John Von Doe'.split(/ (.*)/);
console.log({ first, last });

[first, last] = 'Surma'.split(/ (.*)/);
console.log({ first, last });

Dan Dascalescu
la source
-1

La fonction suivante divisera toujours la phrase en 2 éléments. Le premier élément ne contiendra que le premier mot et le deuxième élément contiendra tous les autres mots (ou ce sera une chaîne vide).

var arr1 = split_on_first_word("72 tocirah sneab");       // Result: ["72", "tocirah sneab"]
var arr2 = split_on_first_word("  72  tocirah sneab  ");  // Result: ["72", "tocirah sneab"]
var arr3 = split_on_first_word("72");                     // Result: ["72", ""]
var arr4 = split_on_first_word("");                       // Result: ["", ""]

function split_on_first_word(str)
{
    str = str.trim();  // Clean string by removing beginning and ending spaces.

    var arr = [];
    var pos = str.indexOf(' ');  // Find position of first space

    if ( pos === -1 ) {
        // No space found
        arr.push(str);                // First word (or empty)
        arr.push('');                 // Empty (no next words)
    } else {
        // Split on first space
        arr.push(str.substr(0,pos));         // First word
        arr.push(str.substr(pos+1).trim());  // Next words
    }

    return arr;
}
Sjoerd Linders
la source
C'est bien trop compliqué .
Dan Dascalescu