2010-05-04 64 views
1

這可能是一個基本的LINQ問題。我需要選擇一個對象,如果它是空的選擇另一個。我使用LINQ to對象以下列方式,我知道可以做到更快,更好,更清潔......如何將這些相似的linq查詢合併爲一個?

public Attrib DetermineAttribution(Data data) 
    { 

     var one = from c in data.actions 
          where c.actionType == Action.ActionTypeOne 
          select new Attrib 
             { 
              id = c.id, 
              name = c.name 
             }; 
     if(one.Count() > 0) 
      return one.First(); 

     var two = from c in data.actions 
        where c.actionType == Action.ActionTypeTwo 
        select new Attrib 
          { 
           id = c.id, 
           name = c.name 
          }; 
     if (two.Count() > 0) 
      return two.First(); 

    } 

兩個LINQ操作上區別僅在where子句,我知道有一種方法將它們結合起來。任何想法將不勝感激。

+1

您應該使用.Any()而不是.Count()。 Count()遍歷整個序列,而Any只檢查第一個項目是否存在。 – Rubys 2010-05-04 15:52:36

+0

@MikeD:應該指出的是,上面的代碼不能編譯,因爲在兩個序列沒有你正在尋找的項目的情況下,你不會返回一個值。 – casperOne 2010-05-04 15:59:53

+0

對不起,我試圖把我的方法清理成SO窗口中的簡明內容,顯然太多了。 – MikeD 2010-05-04 16:54:41

回答

6

我覺得這個解決方案簡單高效:

public Attrib DetermineAttribution(Data data) 
{ 
    var c = data.actions.FirstOrDefault(c => c.actionType == Action.ActionTypeOne) ?? 
      data.actions.FirstOrDefault(c => c.actionType == Action.ActionTypeTwo); 
    return c != null ? new Attrib { id = c.id, name = c.name } : null; 
} 
+0

絕對簡單 – R0MANARMY 2010-05-04 16:00:27

0
var one = (from c in data.actions 
          where (c.actionType == Action.ActionTypeOne) || (c.actionType == Action.ActionTypeTwo) 
          select new Attrib 
             { 
              id = c.id, 
              name = c.name 
             }).FirstOrDefault(); 

這並不能保證在ActionTypeTwo之前會發現ActionTypeOne。它找到第一條記錄ActionTypeOne ActionTypeTwo。

+0

您可以使用orderby來確保檢索項目的順序。 – codymanix 2010-05-04 15:28:24

+0

@codymanix:您必須指定一個自定義比較器,以便在ActionTypeTwo類型的元素之前返回類型爲「ActionTypeOne」的元素(並不保證它們將按默認方式進行排序)。它也需要一些能夠以線性時間運行並將其轉換爲n log(n)的東西。 99%的時間無關緊要,但有一點要注意。 – R0MANARMY 2010-05-04 15:34:27

1

這不使用查詢語法,但它保留了ActionTypeOne類型的元素在ActionTypeTwo的元素之前返回的邏輯。由於懶惰的評估,除非沒有ActionTypeOne類型的元素,否則第二個查詢將不會執行。

public Attrib DetermineAttribution(Data data) 
{ 

    return data.actions.Where(c => c.actionType == Action.ActionTypeOne) 
       .Concat(data.actions.Where(c.actionType == Action.ActionTypeTwo)) 
       .Select(c => new Attrib 
         { 
          id = c.id, 
          name = c.name 
         }) 
       .FirstOrDefault(); 
} 
0

我建議:

public Attrib DetermineAttribution(Data data) 
{ 
     var types = Enum.GetValues(typeof (Action)).Cast<Action>(); 
     var merged = from c in data.actions 
        from t in types 
        where c.actionType == t 
        select new Attrib {id = c.id, name = c.name}; 

     return merged.FirstOrDefault(); 
} 
0
var one = from c in data.actions 
       where c.actionType == Action.ActionTypeOne 
        || c.actionType == Action.ActionTypeTwo 
       orderby c.actionType == Action.ActionTypeOne ? 0 : 1 
       select new Attrib 
           { 
            id = c.id, 
            name = c.name 
           }).FirstOrDefault(); 

等價的SQL查詢將是(我用了一個案例陳述,因爲我不知道操作類型列的數據類型):

​​
相關問題