2013-09-11 3 views
2

У меня есть следующий код, который я хотел бы видеть как oneliner. Однако, так как я новичок в C#, я в настоящее время не имею ни малейшего понятия о том, как это сделать ...Можно ли написать ROT13 в одной строке?

Код:

static string ROT13 (string input) 
{ 
    if (string.IsNullOrEmpty(input)) return input; 

    char[] buffer = new char[input.Length]; 

    for (int i = 0; i < input.Length; i++) 
    { 
     char c = input[i]; 
     if (c >= 97 && c <= 122) 
     { 
      int j = c + 13; 
      if (j > 122) j -= 26; 
      buffer[i] = (char)j; 
     } 
     else if (c >= 65 && c <= 90) 
     { 
      int j = c + 13; 
      if (j > 90) j -= 26; 
      buffer[i] = (char)j; 
     } 
     else 
     { 
      buffer[i] = (char)c; 
     } 
    } 
    return new string(buffer); 
} 

Я извиняюсь за любые неудобства, просто пытаюсь узнать больше об этом симпатичный язык :)

+6

Просто поместите все символы в свой метод на одной строке. –

+2

Любая причина, по которой вы намеренно делаете вещи нечитаемыми? –

+3

Полностью несвязанный, но еще одна вещь, которую вы, возможно, захотите узнать, - это то, что [магические числа] (http://en.wikipedia.org/wiki/Magic_number_ (программирование) #Unnamed_numerical_constants) обычно не очень хорошо. Как показало Save, лучше использовать символы вместо их числовых значений, чтобы лучше показать, что делает код. Как правило, любой код читается более чем в десять раз больше, чем он написан. Поэтому ваша цель всегда заключалась в том, чтобы писать код как можно более понятным и понятным, а не использовать как можно больше умных трюков. Вы можете оптимизировать, когда у вас есть работы. – Corak

ответ

13

Как насчет этого? У меня просто есть этот код, лежащий вокруг, это не очень, но он выполняет эту работу. Просто чтобы убедиться: лайнеры весело, но они обычно не улучшают читаемость и ремонтопригодность коды ... Так что я бы придерживаться своего собственного решения :)

static string ROT13(string input) 
{ 
    return !string.IsNullOrEmpty(input) ? new string (input.ToCharArray().Select(s => { return (char)((s >= 97 && s <= 122) ? ((s + 13 > 122) ? s - 13 : s + 13) : (s >= 65 && s <= 90 ? (s + 13 > 90 ? s - 13 : s + 13) : s)); }).ToArray()) : input;    
} 

Если вам нужно больше разъяснений, просто спросите ,

+1

Спасибо за ваш быстрый ответ! Я вставил код в свою программу, и он работает отлично! Я думаю, что я буду больше смотреть на использование? : операторы. – RFerwerda

+0

Это условное утверждение или просто инструкция if ... then ... else .... Значение if заменяется логическим выражением (условием), тогда оно заменяется на? а else заменяется на:. Удачи, рад, что это сработало для вас! – RvdV79

3

Просто альтернативная версия, которая использует другие символы в сравнении, чтобы сделать вещи более «ясно»

static string ROT13(string input) 
{ 
    return !string.IsNullOrEmpty(input) ? new string(input.Select(x => (x >= 'a' && x <= 'z') ? (char)((x - 'a' + 13) % 26 + 'a') : ((x >= 'A' && x <= 'Z') ? (char)((x - 'A' + 13) % 26 + 'A') : x)).ToArray()) : input;   
} 
5

Не совсем один лайнер, но еще короче, чем исходный код и более понятным, чем другой ответ:

static string Rot13(string input) 
{ 
    if(input == null) 
     return null; 
    Tuple<int, int>[] ranges = { Tuple.Create(65, 90), Tuple.Create(97, 122) }; 
    var chars = input.Select(x => 
    { 
     var range = ranges.SingleOrDefault(y => x >= y.Item1 && x <= y.Item2); 
     if(range == null) 
      return x; 
     return (char)((x - range.Item1 + 13) % 26) + range.Item1; 
    }); 

    return string.Concat(chars); 
} 

Другой вариант, что даже лучше выражает то, что происходит в ROT13 это:

static string Rot13(string input) 
{ 
    var lowerCase = Enumerable.Range('a', 26).Select(x => (char)x).ToArray(); 
    var upperCase = Enumerable.Range('A', 26).Select(x => (char)x).ToArray(); 
    var mapItems = new[] 
    { 
     lowerCase.Zip(lowerCase.Skip(13).Concat(lowerCase.Take(13)), (k, v) => Tuple.Create(k, v)), 
     upperCase.Zip(upperCase.Skip(13).Concat(upperCase.Take(13)), (k, v) => Tuple.Create(k, v)) 
    }; 
    var map = mapItems.SelectMany(x => x).ToDictionary(x => x.Item1, x => x.Item2); 

    return new string(input.Select(x => Map(map, x)).ToArray()); 
} 

static char Map(Dictionary<char, char> map, char c) 
{ 
    char result; 
    if(!map.TryGetValue(c, out result)) 
     return c; 
    return result; 
} 
+0

+1 Для удобства чтения по сравнению с моим ответом Даниил! :-) – RvdV79

+1

Если вы только получаете представления Int32 каждого символа в верхнем решении, измените 'return (char) ((x - range.Item1 + 13)% 26) + range.Item1' to' return (char) ((x - range.Item1 + 13)% 26 + range.Item1) ' – snumpy

Смежные вопросы