c#语言中的字符串压缩

krr*_*hna 3 c#

我有一个用c语言成功完成字符串压缩的ac程序,它是C语言中的一种强力方法.例如,如果输入是aabccccdddddddddda,那么输出应该是a2b1c3d11a2.

我用c语言解决了这个问题,取了每个字符并计算出现次数,然后打印出那个字符和它的数量.

我试图将其转换为c#语言.我想知道在c#语言中应该很容易,因为有很多字符串和char内置方法.

有没有办法我们可以在c#中使用lambda表达式或内置的string或char类型的方法在很少的行中执行此操作?

我的C代码是:

        char *encode(char *src)
    {     
          int recurringLen;
          char count[MAX_RLEN];
          char *dest;
          int i, j = 0, k;
          int len = strlen(src);

         // _itoa_s(34,c,10);
          /* If all characters in the source string are different, 
            then size of destination string would be twice of input string.
            For example if the src is "abcd", then dest would be "a1b1c1d1"
            For other inputs, size would be less than twice. 
            test for the scenarios where abababababababababababa bcos output here is a16b11.
            aabbbcccd
            */
           dest = (char *)malloc(sizeof(char)*(len*2 + 1));


          /* traverse the input string one by one */
          for(i = 0; i < len; i++)
          {

            /* Copy the first occurrence of the new character */
            dest[j++] = src[i];

            /* Count the number of occurrences of the new character */
            recurringLen = 1;     
            while(i + 1 < len && src[i] == src[i+1])
            {
              recurringLen++;
              i++;
            }   

            /* Store rLen in a character array count[] */
            sprintf_s(count, "%d", recurringLen);

            /* Copy the count[] to destination */
            for(k = 0; *(count+k); k++, j++)
            { 
              dest[j] = count[k]; 
            } 
          }  

          /*terminate the destination string */
          dest[j] = '\0';
          return dest;
    }     
Run Code Online (Sandbox Code Playgroud)

I4V*_*I4V 8

可以通过编写扩展方法来完成Linqy方式 GroupSeqsBy

string input= "aabccccdddddddddddaa";
var s = String.Join("",input.GroupSeqsBy(c => c)
                            .Select(g => g.Key.ToString() + g.Value.Count()));
Run Code Online (Sandbox Code Playgroud)
public static IEnumerable<KeyValuePair<S, IEnumerable<T>>> GroupSeqsBy<T, S>(this IEnumerable<T> list, Func<T, S> keySelector)
{
    List<T> retList = new List<T>();
    S prev = keySelector(list.FirstOrDefault());
    foreach (T item in list)
    {
        if (keySelector(item).Equals(prev))
            retList.Add(item);
        else
        {
            yield return new KeyValuePair<S, IEnumerable<T>>(prev, retList);
            prev = keySelector(item);
            retList = new List<T>();
            retList.Add(item);
        }
    }
    if (retList.Count > 0)
        yield return new KeyValuePair<S, IEnumerable<T>>(prev, retList);
}
Run Code Online (Sandbox Code Playgroud)


aca*_*lon 5

使用正则表达式你可以做到这一点(假设你的例子有一个错字,其中 c3 应该是 c4)

static readonly Regex re = new Regex( @"(.)\1*", RegexOptions.Compiled );               
static void Main()
{
    string result = re.Replace( "aabccccdddddddddddaa", match => match.Value[0] + match.Length.ToString() );                        
    Console.WriteLine( result );
}
Run Code Online (Sandbox Code Playgroud)

输出是:

a2b1c4d11a2

基本上,我们正在搜索任何重复 0 次或更多次的字符,然后将其替换为后跟匹配字符串长度的字符。

具体来说: -

  • . 匹配任何字符(\n 除外)。
  • (.) 圆括号进行分组
  • \1 是对该组的编号反向引用,基本上是重新使用已经匹配的字符。
  • * 是一个重复运算符,表示重复匹配 0 次或更多次。我们也可以使用 {0,}。

一些有用的链接是: Grouping | 重复| C# 正则表达式| C# 匹配委托| C# 正则表达式快速参考| C# 反向引用

如果您希望这是字符串的扩展(不确定这是否是必需的),则:

public static class StringExtensions
{ 
    static readonly Regex re = new Regex( @"(.)\1*", RegexOptions.Compiled );                
    public static string Compress(this string theString)
    {
        return re.Replace( theString, match => match.Value[0] + match.Length.ToString() );             
    }
}
Run Code Online (Sandbox Code Playgroud)

使用方法如下:

string theString = "aabccccdddddddddddaa";
string result = theString.Compress();
Run Code Online (Sandbox Code Playgroud)