2016-01-02 11 views
5

Szukam wyrażeń regularnych, które usuwają wszystkie znaki, które zostały powtórzone w ciągu znaków. Rozwiązałem już to za pomocą pętli. Zastanawiam się, czy istnieje regex, który może zrobić to samo.Regex, aby usunąć wszystkie znaki, które się powtarzają

to, co mam do tej pory:

function onlyUnique(str) { 
    var re = /(.)(?=.*\1)/g 
    return str.replace(re, ''); 
} 

Ten napis:

"rc iauauc!gcusa_usdiscgaesracg" 

powinien skończyć jak ten:

" !_de" 
+1

Chcę usunąć każdy znak znajdujący się w ciągu znaków więcej niż jeden raz. –

+0

To nie jest duplikat [Regex usuń powtarzające się znaki z ciągu znaków przez javascript] (http://stackoverflow.com/q/19301806/1529630). To chce usunąć wszystkie wystąpienia, zamiast pozostawiać tylko pierwsze. – Oriol

+0

^^ i pytanie, OP chce usunąć tylko kolejne powtórzenia. – Tushar

Odpowiedz

1

Twój regex szuka pary znaków powielanych i usuwa tylko pierwszą. Dlatego najnowszy duplikat nie zostanie usunięty.

Aby rozwiązać ten problem, powinieneś usunąć wszystkie duplikaty jednocześnie, ale nie sądzę, że możesz to zrobić z pojedynczym replace.

Zamiast tego, chciałbym zbudować mapę, która zlicza wystąpienia każdego znaku, a następnie ponownie iteracyjne ciąg, pchanie znaki, które pojawiły się tylko raz do nowego napisu:

function onlyUnique(str) { 
    var map = Object.create(null); 
    for(var i=0; i<str.length; ++i) 
    map[str[i]] = (map[str[i]] || 0) + 1; 
    var chars = []; 
    for(var i=0; i<str.length; ++i) 
    if(map[str[i]] === 1) 
     chars.push(str[i]); 
    return chars.join(''); 
} 

przeciwieństwie indexOf, przeszukuje mapa skrótu jest stała. Zatem koszt połączenia z ciągiem znaków n będzie wynosił n.

+0

tak to zrobiłem. Zastanawiam się tylko, czy istnieje pojedyncze wyrażeń regularnych, które również mogą to zrobić. –

1

dobrze, nie wiem, czy regex może to zrobić, ale można się dogadać za pomocą pętli for, jak:

function unikChars(str) { 
    store = []; 
    for (var a = 0, len = str.length; a < len; a++) { 
     var ch = str.charAt(a); 
     if (str.indexOf(ch) == a && str.indexOf(ch, a + 1) == -1) { 
      store.push(ch); 
     } 
    } 
    return store.join(""); 
} 

var str = 'rc iauauc!gcusa_usdiscgaesracg'; 
console.log(unikChars(str)); //gives !_de 

Demo :: jsFiddle

3

Można skorzystać z Array#indexOfArray#filter i Array#lastIndexOf do sprawdź, czy element się powtarza.

var str = "rc iauauc!gcusa_usdiscgaesracg"; 
 

 
// Split to get array 
 
var arr = str.split(''); 
 

 
// Filter splitted array 
 
str = arr.filter(function (e) { 
 
    // If index and lastIndex are equal, the element is not repeated 
 
    return arr.indexOf(e) === arr.lastIndexOf(e); 
 
}).join(''); // Join to get string from array 
 

 
console.log(str); 
 
document.write(str);

1

Jeśli chcesz zrobić to z regex, można użyć własnego regex z funkcji wywołania zwrotnego wewnątrz zastąpić.

var re = /(.)(?=.*\1)/g; 
 
var str = 'rc iauauc!gcusa_usdiscgaesracg'; 
 
var result = str; 
 
str.replace(re, function(m, g1) { 
 
    result = result.replace(RegExp(g1.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), ''); 
 
}); 
 
document.getElementById("r").innerHTML = "'" + result + "'";
<div id="r"/>

Chodzi o to: uzyskać kopiowane charakter i usunąć go z ciągu wejściowego. Zauważ, że wymuszenie jest konieczne, jeśli znak może być metaznakiem specjalnym regex (w ten sposób użyto g1.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).

Innym pomysłem należący do Washington Guedes w his deleted answer, po prostu dodać własną implementację tutaj (z usuwania duplikatów symbole z klasy postaci i ucieczki znaki specjalne regex):

var s = "rc iauauc!gcusa_u]sdiscgaesracg]"; 
 
var delimiters= '[' + s.match(/(.)(?=.*\1)/g).filter(function(value, index, self) { // find all repeating chars 
 
    return self.indexOf(value) === index; // get unique values only 
 
}).join('').replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + ']'; // escape special chars 
 
var regex = new RegExp(delimiters, 'g'); // build the global regex from the delimiters 
 
var result = s.replace(regex, ''); // obtain the result 
 
document.getElementById("r2").innerHTML = "'" + result + "'";
<div id="r2"/>

UWAGA: jeśli chcesz także obsługiwać znaki nowej linii, zamień . na [^] lub [\s\S] wewnątrz wzorca regex.

0
function onlyUnique(str) { 
    // match the characters you want to remove 
    var match = str.match(/(.)(?=.*\1)/g); 
    if (match) { 
    // build your regex pattern 
    match = '[' + match.join('') + ']'; 
    } 
    // if string is already unique return the string 
    else { 
    return str 
    } 
    // create a regex with the characters you want to remove  
    var re = new RegExp(match, 'g'); 
    return str.replace(re, ''); 
} 
+0

Proszę dodać wyjaśnienie do swojej odpowiedzi. Odpowiedzi tylko na kod są ogólnie uważane za niskiej jakości – Tristan

Powiązane problemy