2015-04-04 60 views
1

我有一个Linq查询的结果,我想用它做一些字符串操作和连接。IEnumerable集合的并置C#

结果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的名称,obtainedby

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

产生结果2:

WindDir 
WindVel 

从两个结果想获得一个连续清单如下:(Result3)在动态SQL查询后

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

这些表格列。

我有以下的代码来完成这一步一步:

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列表?

回答

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 lambda语法。

在这种情况下,我认为查询语法更清晰,更容易阅读,但是对于他们自己。

这里与功能证明小提琴:https://dotnetfiddle.net/Z61RsI

+0

嗨,卡梅隆!哇这真棒。 (upvote需要15分,现在只有7分,我很快就达到了15分我会这样做)现在我意识到我对LINQ有多了解。需要了解更多LINQ语法,以及掌握C# 。 (你可能已经理解我已经是一个新的蜜蜂了);-)你的lambda和查询结果都像一个魅力。你可以建议好的书籍,LINQ和C#中的Winforms编程资源?对不起主题。 – Nish 2015-04-04 17:04:28

+0

@Nish有**吨**资源。我个人从工作代码看最好。 [MSDN的Linq资源](https://msdn.microsoft.com/en-us/library/bb397926.aspx)是伟大的。如果您想要代码示例,Microsoft有[101 LInq示例](https://代码。 msdn.microsoft.com/101-LINQ-Samples-3fb9811b)来查看。 – Cameron 2015-04-04 17:58:39

+0

谢谢Cameron。说得通。是啊!祝你有美好的一天 – Nish 2015-04-04 18:58:33

1

Enumerable.Select没有做任何事情重要,当你调用它,它只是进行一些设置,以便根据需要请求的工作将在稍后进行。

所以,当你写

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

这不叫string.Insert呢。只有当您(或您的调试器)稍后开始迭代selCarPostsArrWithC时才调用string.Insert

通常,这并不重要,除了性能,如果你遍历可枚举多次。但是,在这里,由于string.Insert被调用的时间比您预期的要晚,因此您传递给它的参数是也是的计算结果晚于您的预期。您只有一个type变量,并且该变量在读取时已经保存了下一个值。

在一般情况下,你可以通过创建每个迭代一个新的变量,捕获的type的值迭代期间所看到解决这个问题:

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

(如今,C#已经这样做了幕后的背后foreach,但你可能需要将它写出来是这样,如果使用的是老式编译器)

,或者,执行所有的评估直接在循环体内。

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

虽然在这种情况下,最好只制作s2 a List<string>,并调用其AddRange方法。

+0

嗨hvd。感谢您的信息..我试图解决方案形式卡梅隆..它的工作。但是,仍然感谢。您的评论回答了我的代码为什么不起作用。很多LINQ的东西要学:-)。 – Nish 2015-04-04 18:57:13