Bagaimana cara memisahkan string dengan beberapa pemisah dalam javascript?


504

Bagaimana cara memisahkan string dengan beberapa pemisah dalam JavaScript? Saya mencoba untuk membagi pada koma dan spasi tetapi, AFAIK, fungsi pemisahan JS hanya mendukung satu pemisah.


3
Saya punya masalah ini mencoba untuk membagi jalur file yang dibangun dengan nodejs di bawah windows. Terkadang ada garis miring "/" dan "" di belakang.
Fuhrmanator

Jawaban:


707

Lulus dalam regexp sebagai parameter:

js> "Hello awesome, world!".split(/[\s,]+/)
Hello,awesome,world!

Diedit untuk menambahkan:

Anda bisa mendapatkan elemen terakhir dengan memilih panjang array dikurangi 1:

>>> bits = "Hello awesome, world!".split(/[\s,]+/)
["Hello", "awesome", "world!"]
>>> bit = bits[bits.length - 1]
"world!"

... dan jika polanya tidak cocok:

>>> bits = "Hello awesome, world!".split(/foo/)
["Hello awesome, world!"]
>>> bits[bits.length - 1]
"Hello awesome, world!"

1
Apa yang Anda gunakan untuk konsol js> Anda?
core

4
badak, implementasi Mozilla dari JavaScript di Java: mozilla.org/rhino (... atau "sudo apt-get install badak").
Aaron Maenpaa

Terima kasih. pertanyaan lain yang berkaitan dengan ini apa yang perlu saya lakukan adalah mendapatkan elemen terakhir dari array yang terpecah. jika tidak ada array itu harus mengembalikan string thx

2
Apakah ada cara untuk menghindari penghapusan pemisah saat berpisah dengan ekspresi reguler?
Anderson Green

Bagaimana cara membagi untuk string "halo dunia" serta karakter lain (atau regex lainnya), seperti simbol pipa? Variasi yang dicoba (hello world)|\|belum cukup berhasil. Ada ide?
gila tentang rapi

183

Anda bisa memasukkan regex ke operator perpecahan Javascript . Sebagai contoh:

"1,2 3".split(/,| /) 
["1", "2", "3"]

Atau, jika Anda ingin mengizinkan beberapa pemisah bersama untuk bertindak sebagai satu-satunya:

"1, 2, , 3".split(/(?:,| )+/) 
["1", "2", "3"]

(Anda harus menggunakan parens yang tidak menangkap (? :) karena jika tidak maka akan disambungkan kembali ke hasilnya. Atau Anda bisa pintar seperti Aaron dan menggunakan kelas karakter.)

(Contoh diuji dalam Safari + FF)


3
Jika Anda memerlukan beberapa karakter untuk bertindak sebagai satu, seperti dalam, ucapkan "satu; #two; #new jersey", Anda bisa meneruskan string "; #" ke fungsi split. "one; #two; #new jersey" .split ("; #") [2] === "jersey baru"
Oskar Austegard

Metode ini berfungsi lebih baik daripada kelas karakter jika Anda perlu membagi lebih dari satu karakter. Pisahkan mereka |seperti yang ditunjukkan Jesse.
devios1

Saya bertanya-tanya apakah ada cara untuk menghindari menghapus pemisah saat memisahkan string dengan ekspresi reguler: contoh ini menghilangkan pemisah, tapi saya berharap mungkin untuk memisahkan string tanpa menghapusnya.
Anderson Green

1
@AndersonGreen Tergantung pada apa yang Anda inginkan; dalam hal ini, ada beberapa pemisah, jadi apakah Anda ingin menyimpan semuanya? Sebagai barang terpisah? Bergabung dengan item sebelumnya? Item berikutnya? Sepertinya tidak jelas bagi saya. Anda mungkin ingin membuat pertanyaan baru dengan beberapa contoh tentang apa yang Anda cari.
Jesse Rusak

@JesseRusak Maksud saya menjaga semua pemisah sebagai item yang terpisah, sehingga string dapat dipatuhi menggunakan daftar pemisah.
Anderson Green

55

Metode lain yang sederhana namun efektif adalah dengan menggunakan split + join berulang kali.

"a=b,c:d".split('=').join(',').split(':').join(',').split(',')

Pada dasarnya melakukan split diikuti oleh join seperti ganti global sehingga ini menggantikan setiap pemisah dengan koma maka setelah semua diganti itu melakukan split akhir pada koma

Hasil dari ungkapan di atas adalah:

['a', 'b', 'c', 'd']

Memperluas ini Anda juga bisa menempatkannya dalam suatu fungsi:

function splitMulti(str, tokens){
        var tempChar = tokens[0]; // We can use the first token as a temporary join character
        for(var i = 1; i < tokens.length; i++){
            str = str.split(tokens[i]).join(tempChar);
        }
        str = str.split(tempChar);
        return str;
}

Pemakaian:

splitMulti('a=b,c:d', ['=', ',', ':']) // ["a", "b", "c", "d"]

Jika Anda banyak menggunakan fungsi ini, bahkan mungkin patut dipertimbangkan untuk membungkusnya String.prototype.split untuk kenyamanan (saya pikir fungsi saya cukup aman - satu-satunya pertimbangan adalah tambahan overhead dari kondisi (kecil) dan fakta bahwa ia tidak memiliki implementasi dari argumen batas jika sebuah array dilewatkan).

Pastikan untuk memasukkan splitMultifungsi jika menggunakan pendekatan ini di bawah ini hanya membungkusnya :). Juga patut dicatat bahwa beberapa orang tidak suka memperluas built-in (karena banyak orang melakukan kesalahan dan konflik dapat terjadi) jadi jika ragu berbicara dengan seseorang yang lebih senior sebelum menggunakan ini atau bertanya pada SO :)

    var splitOrig = String.prototype.split; // Maintain a reference to inbuilt fn
    String.prototype.split = function (){
        if(arguments[0].length > 0){
            if(Object.prototype.toString.call(arguments[0]) == "[object Array]" ) { // Check if our separator is an array
                return splitMulti(this, arguments[0]);  // Call splitMulti
            }
        }
        return splitOrig.apply(this, arguments); // Call original split maintaining context
    };

Pemakaian:

var a = "a=b,c:d";
    a.split(['=', ',', ':']); // ["a", "b", "c", "d"]

// Test to check that the built-in split still works (although our wrapper wouldn't work if it didn't as it depends on it :P)
        a.split('='); // ["a", "b,c:d"] 

Nikmati!


3
Mengapa kamu menulis for(var i = 0; i < tokens.length; i++)dan tidak for(var i = 1; i < tokens.length; i++)?
tic

Saya telah melewatkan optimasi itu, Anda benar kita dapat mulai tokens[1]untuk menyimpan satu iterasi tokens[0] == tempchardan kami membagi tempcharsetelah iterasi tokensuntuk menyelesaikan. Saya akan memperbarui jawabannya sesuai dengan terima kasih @tic :).
Brian

20

Mari kita tetap sederhana: (tambahkan "[] ​​+" ke RegEx Anda berarti "1 atau lebih")

Ini berarti "+" dan "{1,}" adalah sama.

var words = text.split(/[ .:;?!~,`"&|()<>{}\[\]\r\n/\\]+/); // note ' and - are kept

2
tambahkan "+" pada akhirnya berarti 1 atau lebih
Asher

6
Saya akan mengatakan ini minimal, tidak sederhana
Darryl Hebbes

Untuk tanda + dan - :-D, tetapi juga bukan karakter kosong: var words = text.split (/ [\ s.:;?!~,`"&|()<>{}\= \ + \ - [] \ r \ n / \] + /);
Didier68

12

Metode rumit:

var s = "dasdnk asd, (naks) :d skldma";
var a = s.replace('(',' ').replace(')',' ').replace(',',' ').split(' ');
console.log(a);//["dasdnk", "asd", "naks", ":d", "skldma"]

3
ini salah karena .replace () tidak menggantikan semua elemen:/

1
Anda dapat mengubah '('untuk /(/gmengganti semua (elemen - gadalah bendera global untuk RegExp - sehingga ia mencari semua kejadian yang (bukan yang pertama
codename-

7

Bagi Anda yang ingin lebih banyak kustomisasi dalam fungsi pemisahan mereka, saya menulis algoritma rekursif yang membagi string yang diberikan dengan daftar karakter untuk dibagi. Saya menulis ini sebelum saya melihat posting di atas. Saya harap ini membantu beberapa programmer yang frustrasi.

splitString = function(string, splitters) {
    var list = [string];
    for(var i=0, len=splitters.length; i<len; i++) {
        traverseList(list, splitters[i], 0);
    }
    return flatten(list);
}

traverseList = function(list, splitter, index) {
    if(list[index]) {
        if((list.constructor !== String) && (list[index].constructor === String))
            (list[index] != list[index].split(splitter)) ? list[index] = list[index].split(splitter) : null;
        (list[index].constructor === Array) ? traverseList(list[index], splitter, 0) : null;
        (list.constructor === Array) ? traverseList(list, splitter, index+1) : null;    
    }
}

flatten = function(arr) {
    return arr.reduce(function(acc, val) {
        return acc.concat(val.constructor === Array ? flatten(val) : val);
    },[]);
}

var stringToSplit = "people and_other/things";
var splitList = [" ", "_", "/"];
splitString(stringToSplit, splitList);

Contoh pengembalian di atas: ["people", "and", "other", "things"]

Catatan: flattenfungsi diambil dari Rosetta Code


6

Anda bisa mengelompokkan semua karakter yang ingin Anda gunakan sebagai pemisah, baik tunggal atau kolektif ke dalam ekspresi reguler dan meneruskannya ke fungsi split. Misalnya, Anda dapat menulis:

console.log( "dasdnk asd, (naks) :d skldma".split(/[ \(,\)]+/) );

Dan hasilnya adalah:

["dasdnk", "asd", "naks", ":d", "skldma"]

3

Mungkin Anda harus melakukan semacam penggantian string untuk mengubah satu pemisah menjadi pemisah yang lain sehingga Anda hanya memiliki satu pemisah untuk menangani perpecahan Anda.


3

Hai misalnya jika Anda telah membagi dan mengganti di String 07:05:45

var hour = time.replace("PM", "").split(":");

Hasil

[ '07', '05', '45' ]

3

Berikut adalah cara baru untuk mencapai hal yang sama di ES6 :

function SplitByString(source, splitBy) {
  var splitter = splitBy.split('');
  splitter.push([source]); //Push initial value

  return splitter.reduceRight(function(accumulator, curValue) {
    var k = [];
    accumulator.forEach(v => k = [...k, ...v.split(curValue)]);
    return k;
  });
}

var source = "abc,def#hijk*lmn,opq#rst*uvw,xyz";
var splitBy = ",*#";
console.log(SplitByString(source, splitBy));

Harap dicatat dalam fungsi ini:

  • Tidak ada Regex yang terlibat
  • Mengembalikan nilai yang dibagi dalam urutan yang sama seperti yang muncul di source

Hasil dari kode di atas adalah:

masukkan deskripsi gambar di sini


2
a = "a=b,c:d"

array = ['=',',',':'];

for(i=0; i< array.length; i++){ a= a.split(array[i]).join(); }

ini akan mengembalikan string tanpa charecter khusus.


2

Refactor @Brian saya menjawab

var string = 'and this is some kind of information and another text and simple and some egample or red or text';
var separators = ['and', 'or'];

function splitMulti(str, separators){
            var tempChar = 't3mp'; //prevent short text separator in split down
            
            //split by regex e.g. \b(or|and)\b
            var re = new RegExp('\\b(' + separators.join('|') + ')\\b' , "g");
            str = str.replace(re, tempChar).split(tempChar);
            
            // trim & remove empty
            return str.map(el => el.trim()).filter(el => el.length > 0);
}

console.log(splitMulti(string, separators))


1

Saya menemukan bahwa salah satu alasan utama saya perlu ini adalah untuk membagi jalur file pada keduanya /dan \. Ini sedikit regex yang rumit jadi saya akan mempostingnya di sini untuk referensi:

var splitFilePath = filePath.split(/[\/\\]/);

1

Saya pikir lebih mudah jika Anda menentukan apa yang ingin Anda tinggalkan, bukan apa yang ingin Anda hapus.

Seolah-olah Anda hanya ingin kata-kata bahasa Inggris, Anda dapat menggunakan sesuatu seperti ini:

text.match(/[a-z'\-]+/gi);

Contoh (run snippet):

var R=[/[a-z'\-]+/gi,/[a-z'\-\s]+/gi];
var s=document.getElementById('s');
for(var i=0;i<R.length;i++)
 {
  var o=document.createElement('option');
  o.innerText=R[i]+'';
  o.value=i;
  s.appendChild(o);
 }
var t=document.getElementById('t');
var r=document.getElementById('r');

s.onchange=function()
 {
  r.innerHTML='';
  var x=s.value;
  if((x>=0)&&(x<R.length))
   x=t.value.match(R[x]);
  for(i=0;i<x.length;i++)
   {
    var li=document.createElement('li');
    li.innerText=x[i];
    r.appendChild(li);
   }
 }
<textarea id="t" style="width:70%;height:12em">even, test; spider-man

But saying o'er what I have said before:
My child is yet a stranger in the world;
She hath not seen the change of fourteen years,
Let two more summers wither in their pride,
Ere we may think her ripe to be a bride.

—Shakespeare, William. The Tragedy of Romeo and Juliet</textarea>

<p><select id="s">
 <option selected>Select a regular expression</option>
 <!-- option value="1">/[a-z'\-]+/gi</option>
 <option value="2">/[a-z'\-\s]+/gi</option -->
</select></p>
 <ol id="r" style="display:block;width:auto;border:1px inner;overflow:scroll;height:8em;max-height:10em;"></ol>
</div>


1

Mulai dari solusi @ stephen-sweriduk (yang lebih menarik bagi saya!), Saya telah sedikit memodifikasinya untuk membuat lebih umum dan dapat digunakan kembali:

/**
 * Adapted from: http://stackoverflow.com/questions/650022/how-do-i-split-a-string-with-multiple-separators-in-javascript
*/
var StringUtils = {

  /**
   * Flatten a list of strings
   * http://rosettacode.org/wiki/Flatten_a_list
   */
  flatten : function(arr) {
    var self=this;
    return arr.reduce(function(acc, val) {
        return acc.concat(val.constructor === Array ? self.flatten(val) : val);
    },[]);
  },

  /**
   * Recursively Traverse a list and apply a function to each item
   * @param list array
   * @param expression Expression to use in func
   * @param func function of (item,expression) to apply expression to item
   *
   */
  traverseListFunc : function(list, expression, index, func) {
    var self=this;
    if(list[index]) {
        if((list.constructor !== String) && (list[index].constructor === String))
            (list[index] != func(list[index], expression)) ? list[index] = func(list[index], expression) : null;
        (list[index].constructor === Array) ? self.traverseListFunc(list[index], expression, 0, func) : null;
        (list.constructor === Array) ? self.traverseListFunc(list, expression, index+1, func) : null;
    }
  },

  /**
   * Recursively map function to string
   * @param string
   * @param expression Expression to apply to func
   * @param function of (item, expressions[i])
   */
  mapFuncToString : function(string, expressions, func) {
    var self=this;
    var list = [string];
    for(var i=0, len=expressions.length; i<len; i++) {
        self.traverseListFunc(list, expressions[i], 0, func);
    }
    return self.flatten(list);
  },

  /**
   * Split a string
   * @param splitters Array of characters to apply the split
   */
  splitString : function(string, splitters) {
    return this.mapFuncToString(string, splitters, function(item, expression) {
      return item.split(expression);
    })
  },

}

lalu

var stringToSplit = "people and_other/things";
var splitList = [" ", "_", "/"];
var splittedString=StringUtils.splitString(stringToSplit, splitList);
console.log(splitList, stringToSplit, splittedString);

yang mengembalikan seperti aslinya:

[ ' ', '_', '/' ] 'people and_other/things' [ 'people', 'and', 'other', 'things' ]

1

Cara mudah untuk melakukan ini adalah memproses setiap karakter string dengan pembatas masing-masing dan membangun array dari splits:

splix = function ()
{
  u = [].slice.call(arguments); v = u.slice(1); u = u[0]; w = [u]; x = 0;

  for (i = 0; i < u.length; ++i)
  {
    for (j = 0; j < v.length; ++j)
    {
      if (u.slice(i, i + v[j].length) == v[j])
      {
        y = w[x].split(v[j]); w[x] = y[0]; w[++x] = y[1];
      };
    };
  };

  return w;
};

Pemakaian: splix(string, delimiters...)

Contoh: splix("1.23--4", ".", "--")

Pengembalian: ["1", "23", "4"]


1

Saya akan memberikan implementasi klasik untuk fungsi tersebut. Kode ini berfungsi di hampir semua versi JavaScript dan entah bagaimana optimal.

  • Itu tidak menggunakan regex, yang sulit untuk dipertahankan
  • Itu tidak menggunakan fitur baru JavaScript
  • Itu tidak menggunakan beberapa pemanggilan .split () .join () yang membutuhkan lebih banyak memori komputer

Hanya kode murni:

var text = "Create a function, that will return an array (of string), with the words inside the text";

println(getWords(text));

function getWords(text)
{
    let startWord = -1;
    let ar = [];

    for(let i = 0; i <= text.length; i++)
    {
        let c = i < text.length ? text[i] : " ";

        if (!isSeparator(c) && startWord < 0)
        {
            startWord = i;
        }

        if (isSeparator(c) && startWord >= 0)
        {
            let word = text.substring(startWord, i);
            ar.push(word);

            startWord = -1;
        }
    }

    return ar;
}

function isSeparator(c)
{
    var separators = [" ", "\t", "\n", "\r", ",", ";", ".", "!", "?", "(", ")"];
    return separators.includes(c);
}

Anda dapat melihat kode berjalan di taman bermain: https://codeguppy.com/code.html?IJI0E4OGnkyTZnoszAzf


0

Saya tidak tahu kinerja RegEx, tetapi di sini ada alternatif lain untuk RegEx memanfaatkan HashSet asli dan bekerja dalam kompleksitas O (max (str.length, delimeter.length)) sebagai gantinya:

var multiSplit = function(str,delimiter){
    if (!(delimiter instanceof Array))
        return str.split(delimiter);
    if (!delimiter || delimiter.length == 0)
        return [str];
    var hashSet = new Set(delimiter);
    if (hashSet.has(""))
        return str.split("");
    var lastIndex = 0;
    var result = [];
    for(var i = 0;i<str.length;i++){
        if (hashSet.has(str[i])){
            result.push(str.substring(lastIndex,i));
            lastIndex = i+1;
        }
    }
    result.push(str.substring(lastIndex));
    return result;
}

multiSplit('1,2,3.4.5.6 7 8 9',[',','.',' ']);
// Output: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]

multiSplit('1,2,3.4.5.6 7 8 9',' ');
// Output: ["1,2,3.4.5.6", "7", "8", "9"]

11
Ya, bagaimana kalau Anda benar-benar menguji sesuatu yang Anda tulis? jsperf.com/slice-vs-custom Ini menunjukkan bahwa kode Anda sebenarnya 10 kali lebih lambat dalam contoh ini. Apa yang memberi Anda gagasan bahwa menggunakan 2 kali slice, 2 kali concat, 1 kali split, 1 kali shift dan tidak ada caching panjang yang ramah kinerja?
Petar

Saya memperbarui kode, sekarang hanya ada jumlah irisan minimum tanpa shift, split, dll.
Orhun Alp Oral

0

Bukan cara terbaik tetapi berfungsi untuk Berpisah dengan Pemisah / Pembatas Banyak dan Berbeda

html

<button onclick="myFunction()">Split with Multiple and Different seperators/delimiters</button>
<p id="demo"></p>

javascript

<script>
function myFunction() {

var str = "How : are | you doing : today?";
var res = str.split(' | ');

var str2 = '';
var i;
for (i = 0; i < res.length; i++) { 
    str2 += res[i];

    if (i != res.length-1) {
      str2 += ",";
    }
}
var res2 = str2.split(' : ');

//you can add countless options (with or without space)

document.getElementById("demo").innerHTML = res2;
</script>

-3

Saya menggunakan regexp:

str =  'Write a program that extracts from a given text all palindromes, e.g. "ABBA", "lamal", "exe".';

var strNew = str.match(/\w+/g);

// Output: ["Write", "a", "program", "that", "extracts", "from", "a", "given", "text", "all", "palindromes", "e", "g", "ABBA", "lamal", "exe"]

1
Ini tidak melakukan apa pun dengan palindrom , hanya kata-kata.
Nathan Tuggy
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.