2012-05-09 69 views
4

我在C#中有以下字符串。如何拆分字符串然後重新加入?

"aaa,bbbb.ccc|dddd:eee" 

然後我用new char[] {',','.','|',':'}分割它。我將如何用相同的字符以與先前相同的順序重新加入此字符串?所以這份清單最終會和以前一樣。

string s = "aaa,bbbb.ccc|dddd:eee"; 
string[] s2 = s.Split(new char[] {',','.','|',':'}); 
// now s2 = {"aaa", "bbbb", "ccc", "dddd", "eee"} 
// lets assume I done some operation, and 
// now s2 = {"xxx", "yyy", "zzz", "1111", "222"} 

s = s2.MagicJoin(~~~~~~); // I need this 

// now s = "xxx,yyy.zzz|1111:222"; 

編輯

上述樣品中的char[]只是樣品,而不是在相同的順序,甚至不會全部出現在現實世界中同一時間。

編輯

只是一個想法,怎麼樣使用Regex.split,則首先由char[]拆分得到string[],然後用not the char[]拆分得到另string[],後來只是把它們放回去。也許工作,但我不知道如何編碼。

+1

我認爲你可能需要手動完成。 – Jason

+2

是否總是以完全相同的順序排列? –

+1

看看http://stackoverflow.com/questions/2910536/regex-split-string-but-keep-separators看看是否有幫助。 –

回答

3

可能更容易做到這一點與正則表達式類:

input = Regex.Replace(input, @"[^,.|:]+", DoSomething); 

哪裏DoSomething的是,有關變換項目的方法或λ,例如:

string DoSomething(Match m) 
{ 
    return m.Value.ToUpper(); 
} 

對於這個例子的輸出字符串 「AAA,bbbb.ccc | DDDD:EEE」 將是「AAA ,BBBB.CCC | DDDD:EEE」。

如果您使用lambda,你可以很容易保持周圍狀態,像這樣的:這只是取決於你做的什麼樣的轉變

1,2.3|4:5 

int i = 0; 
Console.WriteLine(Regex.Replace("aaa,bbbb.ccc|dddd:eee", @"[^,.|:]+", 
    _ => (++i).ToString())); 

輸出項目。

+0

謝謝,我認爲這種方式的作品,雖然不是我最初的想法,但我以錯誤的方式開始 –

3

在這裏,你可以使用任何順序的分隔符組合,也可以在字符串中找不到分隔符。我花了一段時間纔想出來,發佈後,它看起來比其他答案更復雜!

好吧,無論如何我都會把它放在這裏。

public static string SplitAndReJoin(string str, char[] delimiters, 
    Func<string[], string[]> mutator) 
{ 
    //first thing to know is which of the delimiters are 
    //actually in the string, and in what order 
    //Using ToArray() here to get the total count of found delimiters 
    var delimitersInOrder = (from ci in 
          (from c in delimiters 
          from i in FindIndexesOfAll(str, c) 
          select new { c, i }) 
          orderby ci.i 
          select ci.c).ToArray(); 
    if (delimitersInOrder.Length == 0) 
    return str; 

    //now split and mutate the string 
    string[] strings = str.Split(delimiters); 
    strings = mutator(strings); 
    //now build a format string 
    //note - this operation is much more complicated if you wish to use 
    //StringSplitOptions.RemoveEmptyEntries 
    string formatStr = string.Join("", 
    delimitersInOrder.Select((c, i) => string.Format("{{{0}}}", i) 
     + c)); 
    //deals with the 'perfect' split - i.e. there's always two values 
    //either side of a delimiter 
    if (strings.Length > delimitersInOrder.Length) 
    formatStr += string.Format("{{{0}}}", strings.Length - 1); 

    return string.Format(formatStr, strings); 
} 

public static IEnumerable<int> FindIndexesOfAll(string str, char c) 
{ 
    int startIndex = 0; 
    int lastIndex = -1; 

    while(true) 
    { 
    lastIndex = str.IndexOf(c, startIndex); 
    if (lastIndex != -1) 
    { 
     yield return lastIndex; 
     startIndex = lastIndex + 1; 
    } 
    else 
     yield break; 
    } 
} 

而且這裏有一個測試,你可以用它來驗證它:

[TestMethod] 
public void TestSplitAndReJoin() 
{ 
    //note - mutator does nothing 
    Assert.AreEqual("a,b", SplitAndReJoin("a,b", ",".ToCharArray(), s => s)); 
    //insert a 'z' in front of every sub string. 
    Assert.AreEqual("zaaa,zbbbb.zccc|zdddd:zeee", SplitAndReJoin("aaa,bbbb.ccc|dddd:eee", 
    ",.|:".ToCharArray(), s => s.Select(ss => "z" + ss).ToArray())); 
    //re-ordering of delimiters + mutate 
    Assert.AreEqual("zaaa,zbbbb.zccc|zdddd:zeee", SplitAndReJoin("aaa,bbbb.ccc|dddd:eee", 
    ":|.,".ToCharArray(), s => s.Select(ss => "z" + ss).ToArray())); 
    //now how about leading or trailing results? 
    Assert.AreEqual("a,", SplitAndReJoin("a,", ",".ToCharArray(), s => s)); 
    Assert.AreEqual(",b", SplitAndReJoin(",b", ",".ToCharArray(), s => s)); 
} 

請注意,我假設你需要能夠做一些與數組中的元素,控制單個再次將它們重新組合在一起之前的字符串 - 否則可能你只會保留原始字符串!

該方法構建一個動態格式字符串。這裏沒有保修效率:)

+0

如果我現在沒有用於分割的'char []'的順序,我只是假設它可能有'char []'。我想爲任何字符串建立一個共同的功能,請諮詢。 –

3

這裏的MagicSplit

public IEnumerable<Tuple<string,char>> MagicSplit(string input, char[] split) 
{  
    var buffer = new StringBuilder(); 
    foreach (var c in input) 
    { 
     if (split.Contains(c)) 
     { 
      var result = buffer.ToString(); 
      buffer.Clear(); 
      yield return Tuple.Create(result,c); 
     } 
     else 
     { 
      buffer.Append(c); 
     } 
    } 
    yield return Tuple.Create(buffer.ToString(),' '); 
} 

和兩種類型的MagicJoin

public string MagicJoin(IEnumerable<Tuple<string,char>> split) 
{ 
    return split.Aggregate(new StringBuilder(), (sb, tup) => sb.Append(tup.Item1).Append(tup.Item2)).ToString(); 
} 

public string MagicJoin(IEnumerable<string> strings, IEnumerable<char> chars) 
{ 
    return strings.Zip(chars, (s,c) => s + c.ToString()).Aggregate(new StringBuilder(), (sb, s) => sb.Append(s)).ToString(); 
} 

用途:

var s = "aaa,bbbb.ccc|dddd:eee"; 

// simple 
var split = MagicSplit(s, new char[] {',','.','|',':'}).ToArray(); 
var joined = MagicJoin(split);  

// if you want to change the strings 
var strings = split.Select(tup => tup.Item1).ToArray(); 
var chars = split.Select(tup => tup.Item2).ToArray(); 
strings[0] = "test"; 
var joined = MagicJoin(strings,chars); 
+0

哈哈+1有趣的方法= D,很好的回答 –

1

這個怎麼樣?

​​

或者,如果你喜歡LINQ(這是我做的):


var x = "aaa,bbbb.ccc|dddd:eee"; 
var matches = Regex.Matches(x, "(?<Value>[^\\.,|\\:]+)(?<Separator>[\\.,|\\:]?)"); 
var reassembly = matches.Cast<Match>().Aggregate(new StringBuilder(), (a, v) => a.AppendFormat("{0}{1}", v.Groups["Value"], v.Groups["Separator"])).ToString(); 
Console.WriteLine(reassembly); 
Console.ReadLine(); 

不用說,你可以做部分的東西重新組裝之前,我會假設是這個練習的點