给定字符串的行程编码

编写给定字符串的运行长度编码的代码
样本输入:aaaaaaaaaabcccccc
输出: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”。

假设它是一个排序的字符串。

这是一个简化版本:

 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循环和字符串构建器的混乱。

添加三元表达式:

 output = grp.Key + (grp.Count() > 1 ? grp.Count().ToString() : "") 

虽然OP确实提到了事后的想法,但在他/她的情况下,他的源字符串已被排序,一般来说, 运行长度编码的输入将不会被排序,因为它将丢失信息并且无法解压缩。 以下是对未排序的更一般情况的看法:

  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 ped,其自身偏移一( Skip ),以便检测连续字符的边界
  • 由于Zip在最短枚举处停止,因此在最短字符串上重复最后一个字符以处理字符串中的最后一个字符。
  • 与其他答案中的“排序”RLE输入字符串不同,分组键是由字符和’是相邻的字符’的组合完成的。 序。
  • GroupBy的投影lambda中,该序列在条件内非常可怕地递增
  • @Jonesy’s / String.Join的条件连接在String.Join用于重新组合最终编码的字符串。

您可以使用条件运算符来解决核心问题。 另一种方法是使用类似于字典和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()))); 

请检查下面的代码,它可能会有所帮助:

 StringBuilder sb = new StringBuilder(); string x = "aaaaaaaaaabcccccc"; char[] c = x.ToCharArray(); char[] t = c.Distinct().ToArray(); for (int i = 0; i < t.Length; i++) { int count = 0; for (int j = 1; j < c.Length; j++) { if (t[i] == c[j - 1]) { count++; } } if (count > 1) { sb.Append(t[i] + count.ToString()); } else { sb.Append(t[i]); } } Console.Write(sb); Console.ReadKey();