2017-03-07 46 views
2

我有一個字符串,其中有括號,括號內可以是另一個括號。例如:以最有效的方式提取字符串中的複雜括號內的字符

var string1 = "1 a (C(b(c+ d)e-fg)) 3# 4df (h j) 5 6 ((k))"; 

每個打開的支架都是關閉的,但不一定是立即關閉的,也就是說,支架內可以是另一個支架。字符,數字和其他符號,如+ - #$%(不包括'!')可以遍佈字符串,分組或單獨。

我想要從括號中提取每個字符(不管它是數字,字母,符號......),並將這些字符格式化爲一個空格,其中包括如果字符串緊接着一個接一個,例如「c +」或「e-fg」,它們將被組合在一起。在上面的例子中,結果將是:

var string2 = "C b c+ d e-fg h j k"; 

我有這樣的代碼,這是否:

var string1 = '1 a (C(b(c+ d)e-fg)) 3# 4df (h j) 5 6 ((k))'; 
var opens = new Array(); 
opens.push(string1.indexOf('(')); 
string1 = string1.replace('(','!') 
var closes = new Array(); 
var done = false; 
while (!done) { 
    openindex = string1.indexOf('('); 
    closeindex = string1.indexOf(')'); 
    string1 = string1.replace(')','!').replace('(','!'); 
    if (openindex>closeindex) { 
     opens.push(openindex); 
     closes.push(closeindex); 
    } 
    if (string1.indexOf(')')==-1) { 
     closes.push(closeindex); 
     done = true; 
    } 
} 
var string2 = ''; 
for (var i=0;i<opens.length;i++) string2 = string2 + string1.substring(opens[i],closes[i]); 
string2 = string2.replace(/!!/g,' ').replace(/!/g,' ').replace(/ /g,' '); 

這可行(https://jsfiddle.net/nL2gp80j/1/),但我正在尋找更有效的解決方案。我不知道正則表達式,也許這可以用它更好更快地實現。

回答

1

有以達到所期望的更短,更好的辦法導致不涉及正則表達式多了很多:

str = '1 a (C(b(c+ d)e-fg)) 3# 4df (h j) 5 6 ((k))'; 
 
array = [], counter = 0; 
 

 
str.split(/([()])/).filter(Boolean).forEach(function(e, i, a) { 
 
    // Increase/decrease counter and push desired values to an array 
 
    e == '(' ? counter++ : e == ')' ? counter-- : counter > 0 ? array.push(e) : true; 
 
    if (i === a.length - 1) 
 
    \t // Join all values with a whitespace between 
 
\t console.log(array.join(' ')); 
 
});

+0

感謝您對之前的雙重檢查接受解決方案 – HenryP

1

使用這個表達式/[^a-z]*/ig它將取代其他一切不是char

var string1 = "1 2 (a(b(c d)efg)) 3 4 (h j) 5 6 ((k))"; 
 
string1 = string1.match(/[a-z]+/ig); 
 
string1=string1.join(" "); 
 
console.log(string1);

[從評論編輯@Jai]

+0

不,字符串是混合的,字符不僅在括號內。正如我在這個問題中寫的,我只用數字來獲得更好的視覺效果。在真實場景中,字符和其他符號(如+ - $%等)都在字符串中。 – HenryP

+1

這將消除括號和空格,它將返回:abcdefghjk。但他也想要空間。 – Sascha

+0

@HenryP而不是否定更好的接受和''.match()'方法提取。 – Jai

1

使用正則表達式來提取與分組的字母。使用String.prototype.match()方法用正則表達式作爲此參數:

var str = "1 2 (a(b(c d)efg)) 3 4 (h j) 5 6 ((k))"; 
 
var ex = str.match(/([a-z])+/g); // will give you grouped letters 
 
console.log(ex.join(" ")); // and join it with a space.

0

使用此,如果確保了支架是在正確的調整。

var string1 = "1 2 (a(b(c d)efg)) 3 4 (h j) 5 6 ((k))"; 
string1 = string1.replace(/[\(\)]*/ig,''); 
alert(string1); 

注意:由於存在複製粘貼錯誤,我編輯了replace-string。

+0

我不知道這是否接近。問題在於,字符不僅在括號內,所有類型的字符都在實際情況下遍佈字符串,正如我在問題中所解釋的。我只將數字和字符分開以便更直觀地顯示。 – HenryP

0

我沒有看到一個簡單的方法來做到這一點的只有一個正則表達式,但這項工作:

var string1 = "1 a (C(b(c+ d)e-fg)) 3# 4df (h j) 5 6 ((k))"; 
 
    // remove before the first (
 
    string1 = string1.replace(/^[^()]*\(/, '('); 
 
    // reome after the last) 
 
    string1 = string1.replace(/\)[^()]*$/g, ')'); 
 
    // remove outside parenthesis 
 
    string1 = string1.replace(/\)[^()]+\(/g, ')('); 
 
    // while there is at least one (
 
    while (string1.indexOf('(') != -1) { 
 
     // remove pair of parenthesis 
 
     string1 = string1.replace(/\(([^()]+)\)/g, " $1 "); 
 
    } 
 
    // remove superfluous spaces 
 
    string1 = string1.replace(/ +/g, ' '); 
 
    console.log(string1);

+0

偉大的,就是這樣,一個正則表達式的解決方案。這比原始代碼快嗎? – HenryP

+0

@HenryP:不確定。你必須做一些benckmark。 – Toto

+1

如果字符串爲'1 a(C(b(c + d)e-fg(test)))3#4df(hj)5 6((k))' – revo

相關問題