2016-04-08 12 views
0

Bir metin dizim var ve belirli bir karakterin (,) en fazla bir tek oluşumunu içerdiğinden emin olmak istiyorum. Bu yüzden birincisini saklamak istiyorum, ancak o karakterin tüm tekrarlarını kaldırmak istiyorum.Bir karakter dizisinin ilk oluşumu hariç tüm bunlar nasıl kaldırılır?

Bunu C# kullanarak en şık şekilde nasıl yapabilirim?

var sb = new StringBuilder(text.Length); 
int maxCount = 1; 
int currentCount = 0; 
char specialChar = ','; 
foreach(char c in text) 
    if(c != specialChar || ++currentCount <= maxCount) 
     sb.Append(c); 
text = sb.ToString(); 

Bu yaklaşım kısa değil ama verimli ve sen Char-sayımı tutmak belirtebilirsiniz:

cevap

2

Sen etkili bir şekilde yeni dize oluşturmak için bir karşı değişken ve bir StringBuilder kullanabilirsiniz.

İşte LINQ kullanarak daha "şık" yoludur:

int commasFound = 0; int maxCommas = 1; 
text = new string(text.Where(c => c != ',' || ++commasFound <= maxCommas).ToArray()); 

bir sorgudan bir değişkeni değiştirmek için gerektirir çünkü bunu sevmiyorum, bu yüzden bir yan etkiye neden oluyor.

+0

oldukça zarif LINQ birini :) – Rawling

+1

@Rawling derim: ben bunu sevmiyorum neden (i LINQ seviyorum bile) yorum yapmak benim cevap düzenlenebilir. –

+0

LINQ ifadenizi gerçekten çok beğendim, ancak henüz bahsettiğiniz yan etkileri anlamıyorum. Orada ne olmasını bekliyorsun? –

3

Bu arama yaptıklarına Sen yere göre iki bölüme dize bölmek aşağıdaki gibi bir fonksiyon yazabiliriz

string a = "12,34,56,789"; 
int pos = 1 + a.IndexOf(','); 
return a.Substring(0, pos) + a.Substring(pos).Replace(",", string.Empty); 
+0

Ben zarif bulmak;) 2 karakter tutmak istiyorsanız sadece bir dezavantajı vardır. –

0

:-) kesin en zarif çalışır, ancak

public static string RemoveAllButFirst(string s, string stuffToRemove) 
{ 
    // Check if the stuff to replace exists and if not, return the original string 
    var locationOfStuff = s.IndexOf(stuffToRemove); 
    if (locationOfStuff < 0) 
    { 
     return s; 
    } 
    // Calculate where to pull the first string from and then replace the rest of the string 
    var splitLocation = locationOfStuff + stuffToRemove.Length; 
    return s.Substring(0, splitLocation) + (s.Substring(splitLocation)).Replace(stuffToRemove,""); 
} 

sadece kullanarak diyebiliriz:

sadece ( String.Replace() kullanarak) ikinci bölümünden eşleşmeleri kaldıracak ve için ( String.Split() yöntemiyle)
var output = RemoveAllButFirst(input,","); 

bir güzel yaklaşım aslında biraz daha temiz bu ele bir uzantısı yöntemi bina içerebilir:

var output = input.RemoveAllButFirst(","); 

yapabilirsiniz see a working example of it here: aracılığıyla aranmak

public static class StringExtensions 
{ 
    public static string RemoveAllButFirst(this string s, string stuffToRemove) 
    { 
      // Check if the stuff to replace exists and if not, return the 
      // original string 
      var locationOfStuff = s.IndexOf(stuffToRemove); 
      if (locationOfStuff < 0) 
      { 
       return s; 
      } 
      // Calculate where to pull the first string from and then replace the rest of the string 
      var splitLocation = locationOfStuff + stuffToRemove.Length; 
      return s.Substring(0, splitLocation) + (s.Substring(splitLocation)).Replace(stuffToRemove,""); 
    } 
} 

.

+0

'StringExtensions'ın statik sınıf olması gerekiyor ve ilk paramın olması gerekiyor 'bu dize s' – Itsik

+0

Nedense benim cevabımın yanıt vermeden orta yanıtı göndermiş gibi görünüyor. Fonksiyonu buna göre güncelledim. Başların için teşekkürler. –

1

Düzenli ifadeler zarif, değil mi?

Regex.Replace("Eats, shoots, and leaves.", @"(?<=,.*),", ""); 

Bu, virgülün önüne geçtiği sürece, hiçbir virgülle değiştirilmez, her virgül yerine geçer.

(Aslında, muhtemelen zarif değil - sadece bir satır kod olabilir, ama aynı zamanda ... O(n^2) olabilir) Linq oneliners gibi reaaaaaaly sizi büyük dizeleri ile anlaşma ve yoksa

+0

bunu bir test cihazına yerleştirdiğimde işe yaramıyor. Bir lookbehind içindeki bir niceleyici, sabit olmayan genişliği – user1040975

+0

@ user1040975 yapar. Farklı bir regex aroması kullanıyor olabilirsiniz. – Rawling

1

:

public static string KeepFirstOccurence (this string @string, char @char) 
{ 
    var index = @string.IndexOf(@char); 
    return String.Concat(String.Concat(@string.TakeWhile(x => @string.IndexOf(x) < index + 1)), String.Concat(@string.SkipWhile(x=>@string.IndexOf(x) < index)).Replace(@char.ToString(), "")); 
} 
0
static string KeepFirstOccurance(this string str, char c) 
    { 
     int charposition = str.IndexOf(c); 
     return str.Substring(0, charposition + 1) + 
        str.Substring(charposition, str.Length - charposition) 
        .Replace(c, ' ').Trim(); 
    } 
-1

Linq ile Pretty kısa; karakter dizisini karakterlere ayırın, farklı kümeleri koruyun ve bir dizeye geri katın.

text = string.Join("", text.Select(c => c).Distinct());