Javascript'te birden çok ayırıcılı bir dizeyi nasıl bölebilirim?


504

JavaScript'te birden çok ayırıcılı bir dizeyi nasıl bölerim? Hem virgül hem de boşluk üzerinde bölmeye çalışıyorum ama AFAIK, JS bölünme işlevi sadece bir ayırıcı destekler.


3
Windows altında nodejs ile inşa edilmiş dosya yollarını ayırmaya çalışırken bu sorunu yaşadım. Bazen aynı yolda ileri "/" ve geri "\" eğik çizgiler vardı.
Fuhrmanator

Yanıtlar:


707

Parametre olarak bir normal ifade girin:

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

Eklemek için düzenlendi:

Eksi 1 dizisinin uzunluğunu seçerek son elemanı alabilirsiniz:

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

... ve desen eşleşmiyorsa:

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

1
Js> konsolunuz için ne kullanıyorsunuz?
çekirdek

4
gergedan, Mozilla'nın Java'daki JavaScript uygulamasını: mozilla.org/rhino (... veya "sudo apt-get install rhino").
Aaron Maenpaa

Teşekkürler. bununla ilgili başka bir soru yapmam gereken bölünmüş dizinin son elemanını almaktır. dizi yoksa thx

2
Normal bir ifadeyle ayrılırken ayırıcıların kaldırılmasını önlemenin bir yolu var mı?
Anderson Green

Boru sembolü gibi bir dize "merhaba dünya" hem de başka bir karakter (veya başka bir normal ifade) için nasıl bölünür? Denenmiş varyasyonları (hello world)|\|henüz işe yaramadı. Herhangi bir fikir?
natty hakkında ceviz

183

Bir regex'i Javascript'in split işlecine geçirebilirsiniz . Örneğin:

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

Veya, birden çok ayırıcının birlikte yalnızca tek bir işlev görmesine izin vermek istiyorsanız:

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

(Yakalamayan (? :) ebeveynleri kullanmalısınız çünkü aksi takdirde sonuca geri eklenir. Veya Aaron gibi akıllı olabilir ve bir karakter sınıfı kullanabilirsiniz.)

(Safari + FF'de test edilen örnekler)


3
Biri gibi davranmak için birden fazla karaktere ihtiyacınız varsa, "one; #two; #new jersey" deyin, split işlevine "; #" dizesini iletebilirsiniz. "one; #two; #new jersey" .split ("; #") [2] === "yeni mayo"
Oskar Austegard

Birden fazla karaktere bölmeniz gerekiyorsa bu yöntem karakter sınıflarından daha iyi çalışır. |Jesse'nin gösterdiği gibi ayırın .
devios1

Düzenli bir ifade ile bir dizeyi ayırırken ayırıcıları kaldırmanın bir yolu var mı acaba: Bu örnek ayırıcıları kaldırır, ancak umarım bunları kaldırmadan bir dizeyi ayırmak mümkündür.
Anderson Green

1
@AndersonGreen Tam olarak ne istediğinize bağlıdır; bu durumda, birden fazla ayırıcı vardır, bu yüzden hepsini tutmak ister misiniz? Ayrı bir ürün olarak mı? Önceki öğeye katıldınız mı? Sıradaki eşya? Benim için belirsiz görünüyor. Aradığın bazı örneklerle yeni bir soru sormak isteyebilirsiniz.
Jesse Rusak

@JesseRusak Tüm ayırıcıları ayrı öğeler olarak tutmak istedim, böylece bir dize ayırıcılar listesi kullanılarak belirlenebilir.
Anderson Green

55

Bir başka basit ama etkili yöntem split + join'i tekrar tekrar kullanmaktır.

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

Temelde bir ayrılma ve ardından bir birleşim yapmak küresel bir değiştirme gibidir, bu yüzden bu her ayırıcıyı bir virgülle değiştirir, sonra hepsi değiştirildikten sonra virgül üzerinde son bir bölünme yapar

Yukarıdaki ifadenin sonucu:

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

Bunu genişleterek bir işleve de yerleştirebilirsiniz:

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

Kullanımı:

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

Bu işlevselliği çok kullanırsanız String.prototype.split, rahatlık için kaydırmayı düşünmeye bile değer olabilir (işlevimin oldukça güvenli olduğunu düşünüyorum - tek düşünce, koşulların (küçük) ek yükü ve sınır bağımsız değişkeninin uygulanmasından yoksun olmasıdır. bir dizi geçirilirse).

splitMultiAşağıya doğru bu yaklaşımı kullanırsanız , işlevi eklediğinizden emin olun :). Ayrıca, bazı insanların yerleşikleri genişletme konusunda kaşlarını çattığına dikkat edin (birçok insan yanlış yapar ve çatışmalar meydana gelebilir), bu yüzden şüpheniz varsa bunu kullanmadan önce daha üst düzey biriyle konuşun veya SO'ya sorun :)

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

Kullanımı:

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

Zevk almak!


3
Neden yazıyorsunuz for(var i = 0; i < tokens.length; i++)değil for(var i = 1; i < tokens.length; i++)?
tic

O optimizasyonu kaçırmıştı, en doğru başlayabiliriz konum tokens[1]olarak bir yineleme kaydetmek tokens[0] == tempcharve biz bölünmüş tempcharyineleme sonra tokensbitirmek için. Cevabı buna göre güncelleyeceğim teşekkürler @tic :).
Brian

20

Basit tutalım: (RegEx'inize "1 veya daha fazla" anlamına gelen bir "[] +" ekleyin)

Bu, "+" ve "{1,}" ifadelerinin aynı olduğu anlamına gelir.

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

2
sonuna "+" ekleyin 1 veya daha fazla anlamına gelir
Asher

6
Ben bu basit, basit değil söyleyebilirim
Darryl Hebbes

+ Ve - :-D için değil, boş karakter yerine \ s için: var words = text.split (/ [\ s.:;?!~,`"&|()<>{\\= \ + \ - [] \ r \ n / \] + /);
Didier68

12

Zor yöntem:

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

3
bu yanlıştır. çünkü .replace () tüm öğelerin yerini almaz:/

1
değiştirebileceğiniz '('için /(/gtüm değiştirmek (unsurları - golduğu küresel RegExp için bayrak - bu tüm oluşumlarını aramak yüzden (değil İlki
codename-

7

Bölme işlevlerinde daha fazla özelleştirme isteyenleriniz için, belirli bir dizeyi bölünecek karakter listesiyle ayıran özyinelemeli bir algoritma yazdım. Yukarıdaki yazıyı görmeden önce bunu yazdım. Umarım bazı sinirli programcılara yardımcı olur.

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

Yukarıdaki örnek şunu döndürür: ["people", "and", "other", "things"]

Not: flattenişlev Rosetta Kodundan alınmıştır


6

Ayırıcı olarak kullanmak istediğiniz tüm karakterleri tek tek veya toplu olarak normal bir ifadeye toplayabilir ve bunları split işlevine geçirebilirsiniz. Örneğin şunları yazabilirsiniz:

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

Ve çıktı:

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

3

Belki de bir ayırıcıyı diğer ayırıcıya dönüştürmek için bir çeşit dize değiştirme yapmalısınız, böylece bölmenizde sadece bir ayırıcıya sahip olursunuz.


3

Merhaba, örneğin Dize'de böl ve değiştir varsa 07:05:45

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

Sonuç

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

3

ES6'da bunu başarmanın yeni bir yolu :

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

Lütfen bu fonksiyonda not edin:

  • Regex dahil değil
  • Bölünmüş değeri, göründüğü sırayla döndürür source

Yukarıdaki kodun sonucu:

resim açıklamasını buraya girin


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

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

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

bu özel bir karakter olmadan dizeyi döndürür.


2

@Brian cevabı için refactorum

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

Bu ihtiyacım ana nedenlerinden biri hem /ve hem de dosya yollarını bölmek olduğunu bulmak \. Biraz zor bir normal ifade bu yüzden buraya referans için göndereceğim:

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

1

Kaldırmak istediklerinizin yerine, ne bırakmak istediğinizi belirtmeniz daha kolay olduğunu düşünüyorum.

Sanki sadece İngilizce kelimeler istiyormuş gibi, şöyle bir şey kullanabilirsiniz:

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

Örnekler (snippet'i çalıştırın):

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

@ Stephen-sweriduk çözümünden başlayarak (bu benim için daha ilginçti!), Daha genel ve yeniden kullanılabilir hale getirmek için biraz değiştirdim:

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

}

ve sonra

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

orijinal olarak geri verir:

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

1

Bunu yapmanın kolay bir yolu, dizenin her karakterini her bir sınırlayıcıyla işlemek ve bölünmeler dizisi oluşturmaktır:

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

Kullanımı: splix(string, delimiters...)

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

İadeler: ["1", "23", "4"]


1

Böyle bir işlev için klasik bir uygulama sağlayacağım. Kod, JavaScript'in neredeyse tüm sürümlerinde çalışır ve bir şekilde optimumdur.

  • Bakımı zor olan regex kullanmaz
  • JavaScript'in yeni özelliklerini kullanmaz
  • Daha fazla bilgisayar belleği gerektiren birden çok .split () .join () çağrısı kullanmaz

Sadece saf kod:

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

Kodun oyun alanında çalıştığını görebilirsiniz: https://codeguppy.com/code.html?IJI0E4OGnkyTZnoszAzf


0

RegEx performansını bilmiyorum, ama burada RegEx yerel HashSet kullanır ve O (max (str.length, delimeter.length)) karmaşıklığı yerine çalışır:

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
Evet, yazdığınız bir şeyi test etmeye ne dersiniz? jsperf.com/slice-vs-custom Bu, kodunuzun bu örnekte aslında 10 kat daha yavaş olduğunu gösterir. Size 2 kez dilim, 2 kez concat, 1 zaman bölünmesi, 1 zaman kaydırma ve uzunluk önbelleklemenin kullanılmasının performans dostu olduğu hakkında fikir veren nedir?
Petar

Kodu güncelledim, şimdi hiçbir değişiklik, bölünme vb.
İle

0

En iyi yol değil, Çoklu ve Farklı ayırıcılar / sınırlayıcılarla Bölme için çalışır

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

Regexp kullanıyorum:

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
Bu palindromlarla hiçbir şey yapmaz , sadece kelimelerle.
Nathan Tuggy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.