簡體   English   中英

IEnumerable集合的串聯C#

[英]Concatenation of IEnumerable collections C#

我有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是group2中啟用的復選框的名稱,由

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

產生Result2:

WindDir
WindVel

從這兩個結果想得到一個串聯列表,如下所示:(Result3)

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 
 }

這里的問題是,在代碼調試過程中,我注意到,只要在foreach行之后點擊F10鍵,然后才實際到達foreach塊,則s2中的先前值將被selCarPostsArrWithC中的后續結果覆蓋。 解釋如下

對於第一次迭代,結果為s2。

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

在第二次迭代的開始之前,先進入foreach塊

s2已經通過WindVel重置為新值,方法如下

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

請任何人能協助我做錯了什么嗎? 如何為IEnumerable列表以粗體顯示Result3?

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設為List<string>並調用其AddRange方法。

基本上,您有一個前綴列表和一個后綴列表。 (注意:我瀏覽了您的代碼,但找不到在每個值后面附加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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM