【问题标题】:Run-length encoding of a given sorted string给定排序字符串的行程编码
【发布时间】:2015-02-18 19:56:05
【问题描述】:

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

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

【问题讨论】:

  • 你的算法是错误的。 aaaaaabccccccaaa 你会得到什么
  • @L.B,对不起。我假设它是一个排序的字符串。

标签: c# linq run-length-encoding


【解决方案1】:

我刚刚发现了一个简短的 RegEx 解决方案。在这里发帖分享,以及great RegEx cheat sheet

Regex.Replace(input, @"(\D)\1+", c => c.Length.ToString() + c.Value[0]);

【讨论】:

【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    尽管 OP 事后确实提到,在他/她的情况下,他的源字符串已排序,但一般来说,Run Length encoding 的输入不会被排序,因为会丢失信息并且无法解压缩。以下是对未排序的更一般情况的看法:

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

    编辑
    我猜数字 cmets 表明某些违反 POLA 需要解释:

    • 字符串为Zipped,自身偏移1 (Skip),以检测连续字符的边界
    • 由于Zip 在最短的枚举上停止,最后一个字符在最短的字符串上重复以处理字符串中的最后一个字符。
    • 与其他答案中的“排序”RLE 输入字符串不同,分组键是由字符和“字符是否相邻?”的组合完成的。排序器。
    • 此序列在GroupBy 的投影 lambda 中的条件内相当可怕地递增
    • @Jonesy's / @Tim's 条件连接在String.Join 中用于重新组装最终的编码字符串。

    【讨论】:

    • 代码有效。如果你能解释一下你的算法,那就太好了。为什么要创建一个长度相同但偏移量为 1 的新字符串?
    • 你是对的 - 代码中有很多令人惊讶的东西 - 我已经更新了一个解释。
    【解决方案4】:

    这是一个简化版:

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

    【讨论】:

    • 它不能完全工作。输入字符串“uuggikejfhhhhtttttii hd”产生输出“u2g2i3kejfh5t5 4d”,最后的h不见了......如果我在开头添加一些东西,比如“aaabbbdddduuggikejfhhhhtttttii hd”,那么输出是“a3b3d5u2g2i3kejfh5t5 4”,现在是d结局也不见了?
    • @CodeOrElse OP 的问题明确引用了Assume that it is a sorted string.,它允许更简单的“分组和计数”策略。我已经在单独的答案中解决了 RLE 的更一般情况。
    【解决方案5】:

    添加三元表达式:

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

    【讨论】:

    • 在 grp 上迭代两次 (grp.Count()) 聪明吗?
    • 运算符 '>' 不能应用于“字符串”和“整数”类型的操作数。
    • @Jonesy:或者括号放错地方了。
    • @TimSchmelter 我不太确定。使用Lookup&lt;TKey, TValue&gt; 不会使其缓存,你能发布一个关于它的链接吗?
    • @TimSchmelter 是的,一个很好的参考,但最好还是避免它。
    【解决方案6】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-18
      • 2016-02-17
      • 2016-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-26
      相关资源
      最近更新 更多