2014-12-19 3 views
4

Написать код для выполнения -длине кодирования заданной строки
Пример ввода: aaaaaaaaaabcccccc
Выход: a10bc6Run-кодирования длины данной строки

Мой код:

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

Я хочу удалить счетчик для неповторяющегося символа, вот «1» для буквы «b».

Предположим, что это отсортированная строка.

+3

Ваш алгоритм неправильно. Что вы получите с 'aaaaaabccccccaaa' –

+0

@ L.B, Извините. Я предполагаю, что это отсортированная строка. –

ответ

2

Вот упрощенная версия:

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.

+0

Не работает. Входная строка «uuggikejfhhhhtttttii hd» производит вывод «u2g2i3kejfh5t5 4d», h в конце пропал ... И если я добавлю что-то в начале, как «aaabbbdddduuggikejfhhhhtttttii hd», тогда выход будет «a3b3d5u2g2i3kejfh5t5 4», теперь d at конец тоже пропал? – CodeOrElse

+1

В вопросе @CodeOrElse OP явно делается ссылка на «Предположим, что это отсортированная строка», которая позволяет более упростить стратегию «группа и счет». Я рассмотрел более общий случай RLE в отдельном ответе. – StuartLC

4

добавить трехкомпонентное выражение:

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

Итерируется по grp дважды ('' grp.Count() '') умный? –

+0

Оператор '>' не может применяться к операндам типа 'string' и 'int'. –

+0

@ Jonesy: или скобки не установлены. –

1

Вы можете использовать условный оператор для выпуска ядра. Другой подход заключается в использовании Lookup, который похож на словарь и 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()))); 
2

Хотя ОП упомянул в качестве запоздалой мысли о том, что в его случае его исходная строка была сортирована, в общем случае входной сигнал 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); 

Edit
Я предполагаю, номерные комментарии указывают на некоторые нарушения POLA, которые требуют объяснения:

  • Строка является Zip PED с (Skip), чтобы определить границы последовательных символов
  • С Zip останавливается на берегу test, последний символ повторяется в кратчайшей строке для обработки конечного символа в строке.
  • В отличие от «сортированной» входной строки RLE в других ответах, групповой ключ выполняется комбинацией символа, а «являются соседними символами»? секвенсор.
  • Эта последовательность довольно ужасающе увеличивается в пределах условной в проекции лямбда от GroupBy
  • @ Джоунси/@ Тима условно присоединиться используется в String.Join собрать окончательную кодированную строку.
+0

Код работает. Если бы вы могли немного объяснить свой алгоритм, было бы здорово. Почему вы создали новую строку с одинаковой длиной и смещением на 1? –

+0

Вы правы - в коде было много удивительных вещей - я обновил объяснение. – StuartLC

0

Пожалуйста, проверьте код, приведенный ниже, это может помочь:

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(); 
Смежные вопросы