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",
]

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


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)


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(" ")

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


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.


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

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


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


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


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.


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 });


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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.