C #: генератор в конце инструкции return

#python #c# #python-3.x #foreach #generator

Вопрос:

У меня есть этот рабочий код Python, который инвертирует регистр всех символов ввода и возвращает результат:

 return ''.join(letter.upper() if letter.islower() else (letter.lower() if letter.isupper() else letter) for letter in input())
 

В этой строке цикл For находится в конце строки вместо строки вместо того, чтобы быть до или на строке над ней.

Возможно ли это в C #? У меня есть рабочая версия функции ниже, где text1 является вводом, но я могу сжать его только до 3 строк вместо 1:

 string result = string.Empty;
foreach(char letter in text1) result  = Char.IsLower(letter) ? letter.ToString().ToUpper() : (Char.IsUpper(letter) ? letter.ToString().ToLower() : letter.ToString());
return resu<
 

Я думал, что этого можно достичь, выполнив это:

 return String.Join('', Char.IsLower(letter) ? letter.ToString().ToUpper() : (Char.IsUpper(letter) ? letter.ToString().ToLower() : letter.ToString()) foreach(char letter in text1));
 

Но синтаксис не позволяет использовать генератор foreach в конце.

Я довольно новичок в C #, поэтому, возможно, я упускаю что-то очевидное, но я не могу найти в Интернете никаких ссылок на наличие генератора в конце такого оператора.

Ответ №1:

(something for x in iterable) в Python есть специальный синтаксис понимания, который можно использовать для создания списков или генераторов на основе существующего итерируемого. Это специальный синтаксис, который разделяет ключевые слова с обычным for циклом, но не имеет прямого отношения к обычным циклам. Синтаксис уникален для Python, и в C # для этого нет прямой замены.

Ближайшей подобной языковой конструкцией в C # были бы выражения LINQ, которые точно соответствуют цели, которая часто стоит за пониманием Python. С выражением LINQ вы можете начать с перечислимого (который является итеративным типом .NET), а затем применить фильтры или сопоставления поверх этого, используя методы Where и Select LINQ .

Итак, рассмотрим следующий пример на Python:

 example = 'Foo Bar!'
result = ''.join(letter.upper() if letter.islower() else (letter.lower() if letter.isupper() else letter) for letter in example)
print(result) #fOO bAR!
 

Прямой эквивалент в C # с использованием LINQ будет выглядеть следующим образом:

 var example = "Foo Bar!";
var result = string.Join("", example.Select(letter =>
    char.IsLower(letter) ? char.ToUpper(letter) :
    char.IsUpper(letter) ? char.ToLower(letter) : letter
));
Console.WriteLine(result); // fOO bAR!
 

Это работает, потому что строка является перечислимым числом символов ( IEnumerable<char> ), и поэтому вы можете использовать Select метод для сопоставления каждой буквы из источника с новым значением.

Комментарии:

1. Почему string.Join , когда разделитель является пустой строкой? Может string.Concat ли это сработать здесь? Отличное объяснение и ответ.

2. Или new string(query.ToArray())

3. @OlivierJacot-Descombes да, много вкусов 🙂

4. @zaggler О да, string.Concat должно работать так же хорошо. Я обычно использую string.Join по привычке, не задумываясь об этом слишком много. Но да, здесь это сработало бы нормально.

5. @poke спасибо за отзыв.