Конкатенация IEnumerable коллекций C #

1

У меня есть 2 результата запроса Linq, с которыми я хочу сделать некоторые строковые операции и объединить.

Результат 1, который является именами разрешенных флажков из группы 1, полученных

var selectedCarPosts = grpBox1MCar.Controls.OfType<CheckBox>()
.Where(c => c.Checked).OrderBy(c => c.Name).Select(c => c.Name);

который дает результат 1:

NearMainGate
NearMP5WestGate

Результат 2, который является именами включенных флажков из группы 2, полученных

var selectedDtTypeCars = gbDataTypeMCars.Controls.OfType<CheckBox>()
.Where(c => c.Checked).OrderBy(c => c.Name).Select(c => c.Name);

который дает результат 2:

WindDir
WindVel

Из обоих результатов хотелось бы получить объединенный список следующим образом: (Результат 3)

C.NearMainGate
C.NearMP5WestGate
C.WindDirNearMainGate
C.WindDirNearMP5WestGate
C.WindVelNearMainGate
C.WindVelNearMP5WestGate

Эти столбцы формируют столбцы в динамическом sql-запросе позже.

У меня есть следующий код для выполнения этого шаг за шагом:

var s1 = selectedCarPosts.Select(s => "C." + s); //the first 2 items in Result3
//Now to get the rest, by inserting Result2 string in each of the first 2 items of Result3
IEnumerable<string> selCarPostsArrWithC = new string[]{};
IEnumerable<string> s2 = new string[]{};
foreach (var type in selectedDtTypeCars)
{
   selCarPostsArrWithC = s1.Select(s => s.Insert(2, type));//C.WindDirNearMainGate C.WindDirNearMP5WestGate in FIRST iteration and so on
   s2 = s2.Concat(selCarPostsArrWithC);// as soon as the SECOND iteration starts, the previous s2 list is overwritten with the subsequent result in selCarPostsArrWithC 
 }

Проблема здесь в том, что во время отладки кода я заметил, что, как только я нажимаю клавишу F10 сразу после строки foreach, перед тем, как фактически достигнуть блока foreach, предыдущие значения в s2 будут перезаписаны последующим результатом в selCarPostsArrWithC уже. Ниже приводится пояснение

Для первой итерации s2 имеет результат.

[0] "C.WindDirNearMainGate"
[1] "C.WindDirNearMP5WestGate"

В начале второй итерации перед входом внутри блока foreach

s2 уже сбрасывает новые значения с помощью WindVel:

[0] "C.WindVelNearMainGate"
[1] "C.WindVelNearMP5WestGate"

Пожалуйста, может кто-нибудь помочь, что я делаю неправильно? Как я могу выполнить Result3 полужирным шрифтом, для списка IEnumerable?

Теги:
linq

2 ответа

0
Лучший ответ

В основном у вас есть список префиксов и список суффиксов. (Примечание: я снял код, и я не мог найти, где у вас есть C. который был добавлен к каждому из значений.)

Для каждого префикса вам нужен суффикс.

Это использование SelectMany()

Я упростил ваш код, потому что вы дали совсем немного кода. Но вот что я придумал:

    var location = new[]
    {
      "NearMainGate", 
      "NearMP5WestGate"
    };

    var modifier = new[]
    {
      "WindDir", 
      "WindVel"
    };

    var lambdaResult = modifier.SelectMany(s => location.Select(l => string.Format("{0}{1}{2}", "C.", s, l)));

    var queryResult =
        from m in modifier
        from l in location
        select string.Format("{0}{1}{2}", "C.", m, l);

Обратите внимание, что существует два решения: синтаксис запроса linq и синтаксис лямбда linq.

В этой ситуации я думаю, что синтаксис запроса чище и легче читать, но каждому свой.

И вот скрипка с доказательством функциональности: https://dotnetfiddle.net/Z61RsI

  • 0
    Привет, Кэмерон! вау Это было круто Большое спасибо. (Голосование требует 15 баллов. Сейчас у меня всего 7 баллов. Как только я достигну 15, я это сделаю) Теперь я понимаю, насколько я новичок в LINQ. Мне нужно больше изучать синтаксис LINQ в дополнение к освоению C # , (вы, возможно, уже поняли, что я совсем новая пчела) ;-) и ваши лямбда-результаты и результаты запросов работают как шарм. Не могли бы вы предложить хорошие книги, ресурсы для программирования на LINQ и Winforms в C #? извините оффтоп.
  • 0
    @Nish Есть тонны ресурсов. Я лично учусь лучше всего, глядя на рабочий код. Ресурсы Linq для MSDN великолепны. Если вам нужны примеры кода, у Microsoft есть 101 пример LInq для просмотра.
Показать ещё 1 комментарий
1

Enumerable.Select не делает ничего важного, когда вы его вызываете, он просто устанавливает все, чтобы запрошенная работа выполнялась позже по желанию.

Поэтому, когда вы пишете

selCarPostsArrWithC = s1.Select(s => s.Insert(2, type));

это не вызывает string.Insert еще. string.Insert вызывается только тогда, когда вы (или ваш отладчик) позже запускаете итерацию через selCarPostsArrWithC.

Обычно это не имеет значения, кроме производительности, если вы повторяете перечислимое несколько раз. Однако здесь, поскольку string.Insert вызывается позже, чем вы ожидаете, аргументы, которые вы передаете ему, также оцениваются позже, чем вы ожидаете. У вас есть только одна переменная type, и эта переменная уже имеет следующее значение к моменту ее чтения.

В общем, вы можете решить это, создав новую переменную на итерацию, которая отображает значение type которое отображается во время этой итерации:

foreach (var type in selectedDtTypeCars)
{
  var type_ = type;
  selCarPostsArrWithC = s1.Select(s => s.Insert(2, type_));
  s2 = s2.Concat(selCarPostsArrWithC);
}

(В настоящее время С# уже делает это за кулисами foreach, но вам, возможно, придется писать это, используя старый компилятор).

Или, альтернативно, выполнить все оценки непосредственно внутри тела цикла:

foreach (var type in selectedDtTypeCars)
{
  selCarPostsArrWithC = s1.Select(s => s.Insert(2, type)).ToList();
  s2 = s2.Concat(selCarPostsArrWithC);
}

Хотя в этом случае было бы лучше просто сделать s2 List<string> и вызвать его метод AddRange.

  • 0
    Привет хвд Спасибо за информацию .. Я попробовал решение формы Кэмерон .. и это сработало. Но все равно спасибо. Ваш комментарий отвечает, почему мой код не работает. много вещей LINQ, чтобы учиться :-).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню