Làm cách nào để phân tách một chuỗi có nhiều dấu phân cách trong javascript?


504

Làm cách nào để phân tách một chuỗi có nhiều dấu phân cách trong JavaScript? Tôi đang cố gắng phân tách trên cả dấu phẩy và dấu cách, nhưng, AFAIK, hàm phân tách của JS chỉ hỗ trợ một dấu phân cách.


3
Tôi gặp vấn đề này khi cố gắng tách các đường dẫn tệp được xây dựng với nodejs dưới windows. Đôi khi có dấu gạch chéo "/" và ngược lại "\" trong cùng một đường dẫn.
Fuhrmanator

Câu trả lời:


707

Truyền vào một biểu thức chính quy như tham số:

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

Chỉnh sửa để thêm:

Bạn có thể lấy phần tử cuối cùng bằng cách chọn độ dài của mảng trừ 1:

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

... và nếu mẫu không khớp:

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

1
Bạn đang sử dụng gì cho js> console của bạn?
lõi

4
tê giác, việc triển khai JavaScript của Mozilla trong Java: mozilla.org/rhino (... hoặc "sudo apt-get install rhino").
Aaron Maenpaa

cảm ơn. một câu hỏi khác liên quan đến điều này những gì tôi cần làm là lấy phần tử cuối cùng của mảng được chia. nếu không có mảng, nó sẽ trả về chuỗi thx

2
Có cách nào để tránh loại bỏ các dấu tách khi tách bằng biểu thức chính quy không?
Anderson Green

Làm thế nào để phân chia cho cả một chuỗi "hello world" cũng như một ký tự khác (hoặc regex khác), như biểu tượng ống? Đã thử các biến thể trong (hello world)|\|đó chưa hoạt động khá. Có ý kiến ​​gì không?
nutty về natty

183

Bạn có thể chuyển regex vào toán tử phân tách của Javascript . Ví dụ:

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

Hoặc, nếu bạn muốn cho phép nhiều dấu phân cách cùng hoạt động như một:

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

(Bạn phải sử dụng parens không bắt (? :) vì nếu không, nó sẽ được ghép lại vào kết quả. Hoặc bạn có thể thông minh như Aaron và sử dụng lớp nhân vật.)

(Ví dụ được thử nghiệm trong Safari + FF)


3
Nếu bạn cần nhiều ký tự để hoạt động như một, như trong, hãy nói "một; #two; #new jersey", bạn có thể chỉ cần chuyển chuỗi "; #" cho hàm phân tách. "một; #two; #new jersey" .split ("; #") [2] === "áo mới"
Oskar Austegard

Phương thức này hoạt động tốt hơn các lớp ký tự nếu bạn cần tách trên nhiều hơn một ký tự. Tách họ bằng |như Jesse cho thấy.
devios1

Tôi tự hỏi liệu có cách nào để tránh loại bỏ các dấu phân tách khi tách một chuỗi bằng một biểu thức chính quy không: ví dụ này loại bỏ các dấu phân cách, nhưng tôi hy vọng có thể tách một chuỗi mà không xóa chúng.
Anderson Green

1
@AndersonGreen Nó phụ thuộc vào chính xác những gì bạn muốn; trong trường hợp này, có nhiều dấu phân cách, vậy bạn có muốn giữ tất cả chúng không? Là một mục riêng biệt? Tham gia vào mục trước? Mục tiếp theo? Có vẻ như không rõ ràng với tôi. Bạn có thể muốn đưa ra một câu hỏi mới với một số ví dụ về những gì bạn đang tìm kiếm.
Jesse Rusak

@JesseRusak Tôi có nghĩa là giữ tất cả các dấu phân tách thành các mục riêng biệt, để một chuỗi có thể được mã hóa bằng cách sử dụng danh sách các dấu phân cách.
Anderson Green

55

Một phương pháp đơn giản nhưng hiệu quả khác là sử dụng split + tham gia nhiều lần.

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

Về cơ bản, việc phân tách được theo sau bởi một phép nối giống như một sự thay thế toàn cầu, vì vậy điều này thay thế mỗi dấu phân cách bằng dấu phẩy sau đó một khi tất cả được thay thế, nó sẽ phân tách cuối cùng trên dấu phẩy

Kết quả của biểu thức trên là:

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

Mở rộng về điều này bạn cũng có thể đặt nó trong một chức năng:

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

Sử dụng:

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

Nếu bạn sử dụng chức năng này rất nhiều, nó thậm chí có thể đáng để xem xét String.prototype.splitcho thuận tiện (tôi nghĩ rằng chức năng của tôi khá an toàn - sự cân nhắc duy nhất là chi phí bổ sung của các điều kiện (thứ yếu) và thực tế là nó thiếu triển khai đối số giới hạn nếu một mảng được thông qua).

Hãy chắc chắn bao gồm splitMultihàm nếu sử dụng phương pháp này dưới đây chỉ đơn giản là kết thúc nó :). Cũng đáng lưu ý rằng một số người cau mày trong việc mở rộng các phần dựng sẵn (vì nhiều người làm sai và có thể xảy ra xung đột), vì vậy nếu nghi ngờ hãy nói với ai đó cao cấp hơn trước khi sử dụng hoặc hỏi trên 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
    };

Sử dụng:

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

Thưởng thức!


3
Tại sao bạn viết for(var i = 0; i < tokens.length; i++)và không for(var i = 1; i < tokens.length; i++)?
tic

Tôi đã bỏ lỡ sự tối ưu hóa đó, bạn nói đúng, chúng ta có thể bắt đầu tokens[1]để lưu một lần lặp tokens[0] == tempcharvà chúng tôi chia ra tempcharsau khi lặp đi lặp lại tokensđể kết thúc. Tôi sẽ cập nhật câu trả lời phù hợp cảm ơn @tic :).
Brian

20

Hãy giữ cho nó đơn giản: (thêm "[] +" vào RegEx của bạn có nghĩa là "1 hoặc nhiều hơn")

Điều này có nghĩa là "+" và "{1,}" giống nhau.

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

2
thêm "+" ở cuối có nghĩa là 1 hoặc nhiều hơn
Asher

6
Tôi muốn nói rằng điều này là tối thiểu, không đơn giản
Darryl Hebbes

Đối với + và - :-D, nhưng cũng thay vì char trống: var words = text.split (/ [\ s.:;?!~,`"&|()<> \ + \ - [] \ r \ n / \] + /);
Didier68

12

Phương pháp khéo léo:

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

3
điều này là sai bởi vì .replace () không thay thế tất cả các yếu tố:/

1
bạn có thể thay đổi '('cho /(/gđến thay thế tất cả (các yếu tố - gtoàn cầu cờ cho RegExp - vì vậy nó tìm kiếm cho tất cả các lần xuất hiện của (không đầu tiên một
codename-

7

Đối với những người muốn tùy chỉnh nhiều hơn trong chức năng chia tách của họ, tôi đã viết một thuật toán đệ quy phân tách một chuỗi đã cho với một danh sách các ký tự để phân tách. Tôi đã viết điều này trước khi tôi thấy bài viết trên. Tôi hy vọng nó sẽ giúp một số lập trình viên nản lòng.

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

Ví dụ trên trả về: ["people", "and", "other", "things"]

Lưu ý: flattenchức năng được lấy từ Rosetta Code


6

Bạn chỉ có thể gộp tất cả các ký tự bạn muốn sử dụng làm dấu phân cách đơn lẻ hoặc tập thể thành một biểu thức chính quy và chuyển chúng sang hàm phân tách. Chẳng hạn, bạn có thể viết:

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

Và đầu ra sẽ là:

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

3

Có lẽ bạn nên thực hiện một số loại chuỗi thay thế để biến một dải phân cách thành dải phân cách khác để sau đó bạn chỉ có một dải phân cách để xử lý trong phân tách của bạn.


3

Xin chào, ví dụ: nếu bạn đã tách và thay thế trong Chuỗi 07:05:45 PM

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

Kết quả

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

3

Đây là một cách mới để đạt được điều tương tự trong 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));

Xin lưu ý trong chức năng này:

  • Không có Regex liên quan
  • Trả về giá trị được chia theo thứ tự như nó xuất hiện trong source

Kết quả của mã trên sẽ là:

nhập mô tả hình ảnh ở đây


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

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

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

điều này sẽ trả về chuỗi mà không có một charecter đặc biệt.


2

Phản hồi của tôi về câu trả lời @Brian

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

Tôi thấy rằng một trong những lý do chính tôi cần điều này là để phân chia đường dẫn tệp trên cả hai /\. Đó là một chút của một regex phức tạp vì vậy tôi sẽ đăng nó ở đây để tham khảo:

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

1

Tôi nghĩ sẽ dễ dàng hơn nếu bạn chỉ định những gì bạn muốn để lại, thay vì những gì bạn muốn loại bỏ.

Như thể bạn chỉ muốn có các từ tiếng Anh, bạn có thể sử dụng một cái gì đó như thế này:

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

Ví dụ (chạy đoạn trích):

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

Bắt đầu từ giải pháp @ stephen-sweriduk (điều đó thú vị hơn với tôi!), Tôi đã sửa đổi một chút để làm cho chung chung hơn và có thể sử dụng lại:

/**
 * 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);
    })
  },

}

và sau đó

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

trả lại như ban đầu:

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

1

Một cách dễ dàng để làm điều này là xử lý từng ký tự của chuỗi với mỗi dấu phân cách và xây dựng một mảng của các phần tách:

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

Sử dụng: splix(string, delimiters...)

Thí dụ: splix("1.23--4", ".", "--")

Trả về: ["1", "23", "4"]


1

Tôi sẽ cung cấp một triển khai cổ điển cho một chức năng như vậy. Mã này hoạt động trong hầu hết tất cả các phiên bản JavaScript và bằng cách nào đó là tối ưu.

  • Nó không sử dụng regex, rất khó để duy trì
  • Nó không sử dụng các tính năng mới của JavaScript
  • Nó không sử dụng nhiều lệnh .split () .join () cần nhiều bộ nhớ máy tính hơn

Chỉ cần mã thuần túy:

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

Bạn có thể thấy mã đang chạy trong sân chơi: https://codeguppy.com/code.html?IJI0E4OGnkyTZnoszAzf


0

Tôi không biết hiệu năng của RegEx, nhưng đây là một giải pháp thay thế khác cho RegEx tận dụng Hashset gốc và hoạt động ở độ phức tạp O (max (str.length, delimet.length)):

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
Vâng, làm thế nào về bạn thực sự kiểm tra một cái gì đó mà bạn viết? jsperf.com/slice-vs-custom Điều này cho thấy mã của bạn thực sự chậm hơn 10 lần trong ví dụ này. Điều gì đã cho bạn ý tưởng rằng sử dụng 2 lần cắt, 2 lần concat, chia 1 lần, 1 lần thay đổi và không có bộ nhớ đệm dài là hiệu suất thân thiện?
Petar

Tôi đã cập nhật mã, bây giờ chỉ có số lượng tối thiểu của lát cắt mà không có sự thay đổi, phân tách hoặc vv
Orhun Alp oral

0

Không phải là cách tốt nhất nhưng hoạt động để phân chia với nhiều phân tách / phân cách khác nhau

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

Tôi sử dụng regrec:

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
Điều này không làm gì với palindromes , chỉ là lời nói.
Nathan Tuggy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.