У меня есть 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?
В основном у вас есть список префиксов и список суффиксов. (Примечание: я снял код, и я не мог найти, где у вас есть 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
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
.