5

与えられた文字列のランレングス エンコーディング用のコードを書く
サンプル入力: aaaaaaaaaaabcccccc
出力: a10bc6

私のコード:

static void Main(string[] args)
{
    string str = "aaaaaaaaaabcccccc";
    var qry = (from c in str
               group c by c into grp
               select new
               {
                   output = grp.Key.ToString() + grp.Count().ToString()
               });
    StringBuilder sb = new StringBuilder();
    foreach (var item in qry)
    {
        sb.Append(item.output);
    }
    Console.WriteLine(sb.ToString());
    Console.ReadLine();
}

ただし、次のように返されます。

a10b1c6

非繰り返し文字のカウントを削除したいのですが、ここでは文字「b」の「1」です。

ソートされた文字列であると仮定します。

4

6 に答える 6

4

三項式を追加します。

output = grp.Key + (grp.Count() > 1 ? grp.Count().ToString() : "")
于 2014-12-19T20:37:02.547 に答える
3

OPは、彼/彼女の場合、ソース文字列がソートされたことを後付けとして言及しましたが、一般に、Run Lengthエンコーディングへの入力はソートされず、情報が失われ、解凍できなくなります。ソートされていないより一般的なケースを次に示します。

  string str = "aaaaaaaabccccccaadddddaaa"; // a8bc6a2d5a3

  // Zip the string with itself, offset by 1 character. 
  // Duplicate the last char to make strings equal length
  var pairs = str
    .Zip((str + str.Last()).Skip(1),
         (prev, current) => new { prev, current });

  // Retain a horrid mutable sequence which tracks consecutive characters
  var sequence = 0;
  var grps = pairs.GroupBy(p => 
    new { Ch = p.prev, 
          Sequence = p.current == p.prev
          ? sequence 
          : sequence++});

  // Join this together, using the other solutions to drop the count from single chars
  var rle = String.Join("", 
    grps.Select(g => g.Count() > 1
        ? g.Key.Ch.ToString() + g.Count().ToString() 
        : g.Key.Ch.ToString()));
  Console.WriteLine(rle);

編集コメントの数は、説明が必要なPOLA
の違反を示していると思います。

  • 文字列は、連続する文字の境界を検出するために、Zipそれ自体を 1 つオフセットして ping されます ( )。Skip
  • 最短の列挙で停止するためZip、最後の文字が最短の文字列で繰り返され、文字列の最後の文字が処理されます。
  • 他の回答の「ソートされた」RLE入力文字列とは異なり、グループ化キーは文字と「文字は隣接していますか?」の組み合わせによって行われます。シーケンサー。
  • このシーケンスは、の射影ラムダの条件内でかなり恐ろしくインクリメントされます。GroupBy
  • @Jonesy の / @Tim の条件付き結合はString.Join、最終的なエンコードされた文字列を再構築するために a 内で使用されます。
于 2014-12-19T21:42:06.807 に答える
1

コアの問題には条件演算子を使用できます。別のアプローチはLookup、辞書に似た a とを使用することString.Concatです。

var charLook = input.ToLookup(c => c);
string result = string.Concat(charLook
    .Select(g => string.Format("{0}{1}", g.Key, g.Count()==1 ? "" : g.Count().ToString())));
于 2014-12-19T20:43:49.303 に答える
1

簡略版は次のとおりです。

public static void Main()
{
   string str = "aaaaaaaaaabcccccc";
    var qry = (from c in str
               group c by c into grp
               let c = grp.Count()
               select grp.Key.ToString() + (c > 1 ? c.ToString() : ""));

    Console.WriteLine(string.Join("",qry));
    Console.ReadLine();
}

三項式を囲むブラケットの配置には注意が必要で、以前はループと文字列ビルダーを使用string.Joinして混乱を避けていました。for each

于 2014-12-19T20:44:55.707 に答える