Имеет ли C # что-нибудь сопоставимое с пониманием списка Python?

Я хочу создать список на C #. Мне не хватает понятий в списках python. Есть ли способ C # для создания коллекций «на лету», например, в виде списков или выражений генератора в python?

5 Solutions collect form web for “Имеет ли C # что-нибудь сопоставимое с пониманием списка Python?”

Если вы используете C # 3.0 (VS2008), то LINQ to Objects могут делать очень похожие вещи:

List<Foo> fooList = new List<Foo>(); IEnumerable<Foo> extract = from foo in fooList where foo.Bar > 10 select Foo.Name.ToUpper(); 

Мэтт упомянул выражения запросов. Они доступны для LINQ в общем, кстати, а не только LINQ to Objects. (Например, тот же запрос, примененный к LINQ to SQL datacontext, будет выполнять фильтр и проекцию в базе данных.)

Выражения запроса в C # 3 – это просто синтаксический сахар над написанием нормального кода C #, хотя выражения запросов обычно заканчиваются вызовами методов расширения . (Им это не нужно, и компилятору все равно, но они обычно это делают.) Существуют различные вещи, которые вы можете делать с коллекциями, которые недоступны в выражениях запросов C #, но которые поддерживаются вызовами методов, поэтому стоит осознавать оба вида синтаксиса. Например, выражение запроса Мэтта:

 List<Foo> fooList = new List<Foo>(); IEnumerable<string> extract = from foo in fooList where foo.Bar > 10 select foo.Name.ToUpper(); 

«предварительно обработан» в:

 List<Foo> fooList = new List<Foo>(); IEnumerable<string> extract = fooList.Where(foo => foo.Bar > 10) .Select(foo => foo.Name.ToUpper()); 

Если вы хотите (скажем) фильтр на основе индекса значения в исходной коллекции, вы можете использовать соответствующую перегрузку Where, которая недоступна с помощью выражений запроса:

 List<Foo> fooList = new List<Foo>(); IEnumerable<string> extract = fooList.Where((foo, index) => foo.Bar > 10 + index) .Select(foo => foo.Name.ToUpper()); 

Или вы можете найти длину самого длинного имени, соответствующего критериям:

 List<Foo> fooList = new List<Foo>(); int longestName = fooList.Where((foo, index) => foo.Bar > 10 + index) .Select(foo => foo.Name) .Max(); 

(Вам не нужно делать проецирование и макс в отдельных методах – есть Max перегрузка, которая также принимает проекцию.)

Я хочу сказать, что с помощью методов расширения вы можете легко создавать сложные запросы.

Вы также упоминаете генераторы Python – C # имеет это в виде блоков итератора . Действительно, они невероятно полезны при реализации LINQ-подобных операторов. (Поскольку большинство LINQ to Objects основаны на методах расширения, вы можете добавить своих собственных операторов, которые выглядят «родными» для LINQ, хотя вы не можете самостоятельно изменить синтаксис выражения запроса.)

List<T>.ConvertAll ведет себя точно так же, как понимание списков, выполняя ту же операцию для каждого элемента существующего списка и затем возвращая новую коллекцию. Это альтернатива использованию Linq, особенно если вы все еще используете .NET 2.0.

В Python простой пример понимания списка:

 >>> foo = [1, 2, 3] >>> bar = [x * 2 for x in foo] >>> bar [2, 4, 6] 

Для C # 3.0 вы можете передать лямбда-функцию, указав, какой тип функции сопоставления необходим.

 public static void Main() { var foo = new List<int>{ 1, 2, 3}; var bar = foo.ConvertAll(x => x * 2); // list comprehension foreach (var x in bar) { Console.WriteLine(x); // should print 2 4 6 } } 

Для C # 2.0 вы можете использовать анонимный метод с делегатом Converter для выполнения эквивалента.

 public static void Main() { List<int> foo = new List<int>(new int[]{ 1, 2, 3}); List<int> bar = foo.ConvertAll(new Converter<int, int>(delegate(int x){ return x * 2; })); // list comprehension foreach (int x in bar) { Console.WriteLine(x); // should print 2 4 6 } } 

(Примечание: то же самое можно сделать с Array.ConvertAll используя Array.ConvertAll

Вот что:

 new List<FooBar> { new Foo(), new Bar() } 

который лишь немного дольше, чем его эквивалент python:

 [Foo(), Bar()] 

И тогда есть следующее:

 public IEnumerable<FooBar> myFooBarGenerator() { yield return new Foo(); yield return new Bar(); } 

который является эквивалентом питона:

 def myFooBarGenerator(): yield Foo() yield Bar() 

Я знаю, что это очень поздний ответ, но я тоже задавался вопросом, имеет ли C # что-либо, эквивалентное пониманию списка python. Ответы от Мэтта Кэмпбелла и Джона Скита показывают, как извлечь список из другого существующего, насколько я понял. Но понимание списка python также может создавать список с нуля. Итак, вот что я придумал.

Сначала я покажу вам понимание списка python, а затем его эквивалент C #, с которым я столкнулся.

Задача игрушки – создать такую ​​строку

 cb01, cb02, cb02, ... , cb50 

Понимание списка Python:

 s = ', '.join('cb{0:02}'.format(i+1) for i in range(50)) 

C # эквивалент Я придумал:

 string s = String.Join(", ", new Func<List<string>>( () => { List<string> list = new List<string>(); foreach (int i in Enumerable.Range(1, 50)) list.Add(String.Format("cb{0:00}", i)); return list; }).Invoke()); 

Я не уверен, что я что-то сделал, или нет.


Изменить: (из того, что Джон Скит упомянул в своем комментарии, настоящий однострочный эквивалент для понимания списком python)

 String.Join(", ", Enumerable.Range(1, 50).Select(x => $"cb{x:00}"))) 

Обратите внимание, что $ thing – это функция C # 6 . Если вы все еще не используете C # 6, вы можете пойти со старым String.Format() .

  • Одиночный оператор Фибоначчи
  • Как объединить 2D-массив в Python в одну строку с помощью List Comprehension?
  • Python исключает дубликаты списка с нераскрывающимися элементами в одной строке
  • Замена элемента списка содержимым другого списка
  • Сортировка понимания списка в одном заявлении
  • Сделать Javascript выполнимым списком
  • Добавление элемента в списки в понимании списка
  • Среднее число номеров, хранящихся в виде строк в списке Python
  • Гарантирован ли порядок результатов, полученных из понимания списка?
  • Создание понимания списка Python с помощью if и break
  • Вложенные петли, использующие понимание списков
  • Python - лучший язык программирования в мире.