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.

mikemaccana
sumber
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!"
Aaron Maenpaa
sumber
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)

Jesse Rusak
sumber
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!

Brian
sumber
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
Asher
sumber
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"]

sumber
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

Stephen Sweriduk
sumber
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"]
PeterKA
sumber
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.

TheTXI
sumber
3

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

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

Hasil

[ '07', '05', '45' ]
Ezequiel García
sumber
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

Wisnu
sumber
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.

gaurav krishna
sumber
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))

JanuszO
sumber
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(/[\/\\]/);
AlliterativeAlice
sumber
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>

ESL
sumber
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' ]
loretoparisi
sumber
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"]

harr-will
sumber
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

codeguppy
sumber
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"]
Orhun Alp Oral
sumber
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>
Stavros
sumber
-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"]
Dodi Ivanov
sumber
1
Ini tidak melakukan apa pun dengan palindrom , hanya kata-kata.
Nathan Tuggy