2012-05-09 15 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"; 

EDIT

上記のサンプルではchar[]ちょうど同じ順序ではなく、サンプルあるいはすべて現実の世界では、同じ時間には表示されません。使用Regex.splitについては、その後、char[]による最初の分割がstring[]を取得する方法だけで考え、

EDIT

、その後ちょうどそれらを戻して、別のstring[]を得る分割するnot the char[]を使用しています。たぶん動くかもしれませんが、コード化する方法がわかりません。

+1

私は手動で行う必要があるかもしれないと思います。 – Jason

+2

は、常に正確に同じ順序で描写されますか? –

+1

http://stackoverflow.com/questions/2910536/regex-split-string-but-keep-separatorsをご覧ください。 –

答えて

3

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

用途Regexクラス:

doSomethingのは、問題のアイテムを変換する方法またはラムダである
input = Regex.Replace(input, @"[^,.|:]+", DoSomething); 

、例えば:

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

この例では "AAA、bbbb.ccc | DDDD:EEE" の出力文字列は「AAAだろう、BBBB.CCC | DDDD:EEE "となります。

あなたは非常に簡単にこのように、周りの状態を保つことができるラムダを使用する場合:

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

出力:

1,2.3|4:5 

をそれはちょうどあなたがやっている変換の種類に依存しますアイテム。

+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の2種類:これを実行する方が簡単かもしれません

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

言うまでもないが、この演習のポイントです

関連する問題