2009-05-25 120 views
3

我有兩個IEnumerable的通過Lambda方式填充ToDictionary()方法中的值字段?

IEnumerable<MyObject> allowedObjects = MyService.GetAllowedObjects(); 
IEnumerable<MyOBject> preferedObjects = MyService.GetPreferedObjects(); 

我們可以有把握地認爲preferedObjects永遠是allowedObjects的一個子集。
我想創建一個IDictionary<MyObject, bool>。如果MyObject實例也位於preferredredObjects枚舉中,則該對象的關鍵是來自allowedObjects和bool的MyObjects集合。

我可以列舉他們通過一個添加它們這樣做,但我希望能夠做這樣的事情:

IDictionary<MyObject, bool> selectedObjects = allowedObjects 
    .ToDictionary(o => new KeyValuePair<MyObject, bool>() 
     { Key = q, 
      Value = preferedObjects.Any(q) 
     } 
    ); 

UPDATE
交換了任何包含; 該建議最該解決方案是我第一次嘗試,但不接受某些原因:

IDictionary<MyObject, bool> selectedObjects = allowedObjects 
    .ToDictionary<MyObject, bool>(o => o, preferedObjects.Any(o)); 

Visual Studio中說,第一種方法不返回布爾。這是真的,但主要是因爲一個布爾不會是正確的結果開始...
然後它說它不能infere第二lambda的類型...
正如你可以看到我試圖明確定義類型來幫助推斷,但它並不能解決一件事情。

建議?

免責聲明:名稱和代碼snippyfied,以保持它應該是

+0

您沒有將第二個參數定義爲lambda表達式!在`preferedObjects.Any(o)`之前加入`o =>`位,它應該可以正常工作(不需要指定泛型類型或使用`Any`而不是`Contains`)。 – Noldorin 2009-05-25 09:40:00

回答

4

我不記得是否的LINQ提供了一個「包含」在IEnumerable<T>擴展方法的焦點。如果沒有,你可以使用任何:

var dict = allowedObjects.ToDictionary(o => o, 
    o => preferredObjects.Contains(o)); 

**編輯**沒錯,只是測試它也的確是一個載有()擴展方法,所以上面的代碼工作。

+0

Bizar,這裏這個語法似乎不起作用: 我真正的代碼: 字典<質量,布爾> selectedQualities = allowedQualities .ToDictionary <質量,布爾>(K => K,V => preferedQualities.Any(V) ); 隨着第一個Q VS說它不能將我的質量轉換爲布爾值;第二個lambda(五)它說它不能推斷出這種類型...... – 2009-05-25 09:10:57

+0

那很奇怪。我測試了幾個IEnumerable 變量,所以您可能會使用Quality類來混淆編譯器。 – 2009-05-25 09:22:09

+0

我想是這樣,但我擔心它超出了範圍(和我的同意不透露)找到問題到底是什麼。 – 2009-05-25 09:36:21

2

Enumerable.ToDictionary有多重過載。其中的一些需要第二個委託(因此您可以傳遞一個lambda)來返回值,並使用該鍵。

喜歡的東西:

var secondDict = firstDictionary 
       .Where(p => SomeCondition(p)) 
       .ToDictionary(p => p.Key, p => p.Value); 
1

就快:

IDictionary<MyObject, bool> selectedObjects = allowedObjects 
    .ToDictionary(o => o, o => preferedObjects.Contains(q)); 

ToDictionary擴展方法能解決使用兩個lambda表達式生成鍵/值對,而不是KeyValuePair類型。

您可以通過使用HashSet<T>對象爲您的allowedObjectspreferredObjects集合大幅加快速度,但我不會打擾,除非您的列表特別大/性能非常重要。

1

你當然可以創建自己的擴展方法。 ToDictionary通過添加源中的所有元素作爲值並使用lambda作爲鍵來創建字典。你可以用不同的方法創建你自己的。當你使用'contains'時,我認爲這樣做不是一個好主意,因爲這是一個緩慢的操作(線性搜索,對於allowedObjects中的每個元素,你正在枚舉preferredobjects)。

一種方法可能是將所有preferredobjects添加到HashSet並在其上使用Contains。另一個可能是使用linq查詢,在其中您將preferredObjects與preferredObjects結合使用,使用加入並使用DefaultIfEmpty。這更有效率:

List<MyObject> allowedObjects = new List<MyObject>() { new MyObject("one"), new MyObject("two"), new MyObject("three")}; 
List<MyObject> preferredObjects = allowedObjects.Take(2).ToList(); 

var q = from a in allowedObjects 
     join p in preferredObjects on a equals p into ap 
     from x in ap.DefaultIfEmpty() 
     let isPreferred = (x != null) 
     let toUse = x ?? a 
     select new { toUse, isPreferred }; 

Dictionary<MyObject, bool> selectedObjects = new Dictionary<MyObject, bool>(); 
foreach(var v in q) 
{ 
    selectedObjects.Add(v.toUse, v.isPreferred); 

    Console.WriteLine("{0}, {1}", v.toUse.Foo, v.isPreferred); 
} 
相關問題