2013-02-26 26 views
3

我有一個對象列表,我必須編寫一個方法,根據輸入參數(這是一個Type的數組)提取一些元素。該函數必須從列表中返回一個元素數組,每個元素都是類型數組中的一個元素的一個實例。同時,這些元素必須從容器列表中刪除,但前提是它們必須存在於列表中。型號比較通過Type.IsInstanceOfType(o)方法實現。提取與LINQ的特定類型的列表元素

class A {} 
class B : A {} 
class C : A {} 
class D : A {} 

public static A[] ExtractElements (List<A> list, Type[] specifiers) {...} 

Type[] specifiers1 = new Type[2] {typeof(D), typeof(B)}; 
Type[] specifiers2 = new Type[3] {typeof(C), typeof(A), typeof(D)}; 
Type[] specifiers3 = new Type[2] {typeof(A), typeof(A)}; 
Type[] specifiers4 = new Type[2] {typeof(C), typeof(C)}; 

List<A> list = new List<A> {new B(), new A(), new D(), new C(), new A()}; 
A[] result1 = ExtractElements (list, specifiers1); 

list = new List<A> {new B(), new A(), new D(), new C(), new A()}; 
A[] result2 = ExtractElements (list, specifiers2); 

list = new List<A> {new B(), new A(), new D(), new C(), new A()}; 
A[] result3 = ExtractElements (list, specifiers3); 

list = new List<A> {new B(), new A(), new D(), new C(), new A()}; 
A[] result4 = ExtractElements (list, specifiers4); 

這個代碼段的結果將是:

result1 is {D, B}, list is {A, C, A} 
    result2 is {C, B, D}, list is {A, A} 
    result3 is {B, A}, list is {D, C, A} 
    result4 is empty array, list is {B, A, D, C, A} 

作爲一個單獨的努力將是可能的,如果列表中包含的請求項目寫入類似ExtractElements方法,該方法僅返回非空數組類型在列表中,其順序對應於類型的輸入數組中的元素的這樣的代碼片段的以下

Type[] specifiers5 = new Type[2] {typeof(B), typeof(D)}; 
Type[] specifiers6 = new Type[2] {typeof(C), typeof(B)}; 

List<A> list = new List<A> {new B(), new A(), new D(), new C(), new A()}; 
A[] result5 = ExtractElements (list, specifiers5); 

list = new List<A> {new B(), new A(), new D(), new C(), new A()}; 
A[] result6 = ExtractElements (list, specifiers6); 

結果的順序將是:

result5 is {B, D}, list is {A, C, A} 
result6 is empty array, list is {B, A, D, C, A} 

我知道LINQ是實現這種方式,但不幸的是,我與它沒有任何經驗。

回答

1

如何:

public IEnumerable<TType> ExtractElements<TType>(IEnumerable<TType> list, IEnumerable<Type> specifiers) { 
    var specifiersList = specifiers.ToList(); 

    return list.Where(t => specifiersList.Any(s => s.IsAssignableFrom(t.GetType()))); 
} 

var specifiers5 = new[] {typeof(B), typeof(D)}; 
var list = new List<A> {new B(), new A(), new D(), new C(), new A()}; 

// you can call ToArray() if you want but ForEach won't be available on that 
// and you'll need a standard foreach() loop 
var result5 = ExtractElements(list, specifiers5).ToList(); 

result5.ForEach(Console.WriteLine); 

對於more informationType.IsAssignableFrom()

+0

似乎要做的伎倆。我有一個控制檯應用程序和一個工作示例。 – 2013-02-26 19:27:14

0

這聽起來像一個完美契合Enumerable.OfType<T>()

+0

我想你可能已經擊中了它的頭。刪除我的答案。出於某種原因,我害怕使用這種方法,但一直都是新的。我正在考慮調用Enumerable.Cast ,我知道它在運行時可能會被淹沒。 – 2013-02-26 18:57:44

+0

哦,等待,唯一的問題是他有多種類型,他想檢查。 – 2013-02-26 19:03:29

+0

啊,對。這確實會讓事情變得不合時宜。 (upvoted你的答案) – hometoast 2013-02-26 19:09:01

0

這應該讓你得到你想要的一切。我爲ExtractElements方法添加了一個可選參數,該參數允許您啓用/禁用訂單匹配。

public static A[] ExtractElements (List<A> list, Type[] specifiers, bool orderMatters = false) 
{ 
    var allFound = true; 
    var listBackup = list.ToList(); // Make a backup copy 
    var returnList = new List<A>(); 
    var earliestMatch = 0; 

    foreach (var spec in specifiers) 
    { 
     var item = list.FirstOrDefault (i => spec.IsAssignableFrom(i.GetType())); 
     if (item != null) 
     { 
      var matchPosition = list.IndexOf(item); 
      if (orderMatters && matchPosition < earliestMatch) // we have an out of order match 
      { 
       allFound = false; 
       break; 
      } 
      earliestMatch = matchPosition; 
      list.Remove(item); 
      returnList.Add(item); 
     } 
     else 
     { 
      allFound = false; 
      break; 
     } 
    } 

    if(!allFound) 
    { 
     // Can't just assign list to listBackup because we have to update the 
     // underlying values not the reference that was passed to the function. 
     list.Clear(); 
     listBackup.ForEach(i => list.Add(i)); 
     returnList.Clear(); 
    } 

    return returnList.ToArray(); 
} 

我建議抓住的LinqPad副本來幫助你測試任何LINQ語句和學習一般LINQ

希望這會有所幫助。

+0

哦哇...我只是意識到他想修改傳入的集合。我只是讓你從這裏拿走它。 – 2013-02-27 01:52:57

+0

是的,這使得它更加尷尬。 – 2013-02-27 02:32:20

+0

毫無疑問 – 2013-02-27 02:58:06