2010-11-20 75 views
0

這是我在這裏討論過的最難的問題之一。 :)雖然標題可能沒有意義,但希望問題本身會。在傳遞函數之前轉換數據的簡單方法?

比方說,我有這樣一個Dictionary<string, List<double>>的數據結構,和我有函數,然後採取List<double> S作爲參數:

Dictionary<string, List<double>> candy_positions = new Dictionary<string, List<double>>(); 
candy_positions.Add("Godiva", new List<double> { 1.0, 2.0, 4.0 }); 
EatCandy(candy_positions["Godiva"]); 
... 

但現在我已經決定,我並不想這樣做這條路。我想用一個List<CandyPositions>,其中CandyPositions看起來像這樣來代替我的Dictionary

public class CandyPositions 
{ 
    public double Sees; 
    public double Godiva; 
    public double Lindt; 
} 

可是,我真的想()獨自離開EatCandy。顯然,現在的問題是我的數據不適合直接傳遞給方法。相反,我必須做喜歡的事,瘸子:

List<CandyPositions> candy_positions = new List<CandyPositions>(); 
... 
var positions = from x in candy_positions select x.Godiva; 
EatCandy(positions.ToList()); 

一次我要調用的方法。我寧願是能夠做到這一點更簡單的方法,如:

EatCandy(candy_positions.GetPositionsFor("Godiva")); 

其中參數「戈黛娃」在CandyPositions類屬性名相匹配。

寫完這個問題後,我意識到它並不是真的關於轉置數據 - 它的一部分可以通過編寫擴展方法來處理。我不知道該怎麼做的部分是傳入一個屬性名稱,以便擴展方法可以將其與一個類的屬性相關聯。我不想傳入字符串,主要是因爲這會打開各種運行時錯誤的大門。我知道如何通過將「Godiva」傳遞給我的擴展方法來完成這項工作。我真正想傳入的內容與CandyPositions.Godiva類似。

這個問題可能是有點混亂,因此,在總結,我會接受最好的兩種答案的:

  1. 有沒有更好的方式來處理移調數據,而不是使用擴展方法+某種方式訪問​​屬性名稱?
  2. 有沒有辦法指定我希望我的擴展方法檢索的屬性,而不是字符串?

我目前的擴展方法是這樣的:

public static List<double> GetPositions(this List<CandyPositions> positions, string candy_name) 
{ 
    return (from x in positions select x.GetType().GetProperty(candy_name).GetValue(x, null)).Cast<double>().ToList(); 
} 

回答

1

嗯,你可以使用:

public static List<double> GetPositions(this List<CandyPositions> positions, 
             Func<CandyPositions, double> projection) 
{ 
    return positions.Select(projection).ToList(); 
} 

,並稱之爲:

EatCandy(candyPositions.GetPositions(x => x.Godiva)); 

在另一方面,如果您可以將EatCandy更改爲接受IEnumerable<double>相反,你不需要額外的方法 - 你可以用:

EatCandy(candyPositions.Select(x => x.Godiva)); 

,而完全不寫一個額外的方法。

編輯:如果你需要一次遍歷兩個序列,有兩種選擇:

  • 如果您使用.NET 4,你可以使用Zip擴展方法。
  • 否則,你基本上可以寫你自己:

    using (var iterator1 = sequence1.GetEnumerator()) 
    using (var iterator2 = sequence2.GetEnumerator()) 
    { 
        while (iterator1.MoveNext() && iterator2.MoveNext()) 
        { 
         var value1 = iterator1.Current; 
         var value2 = iterator2.Current; 
         // Use the values here 
        } 
    } 
    
+0

哇,甚至都沒有發生,我認爲非常酷的做法。謝謝,喬恩!還有一個脫離主題的評論 - 我很高興我的新C#書的訂單將於下週發佈。 :) – Dave 2010-11-20 08:09:01

+0

在我的特殊情況下,我不能使用IEnumerable ,因爲我只需要通過索引訪問數據,因爲我有兩個列表,以及一個類似'a [i] .foo(b [i] )'。我一直認爲這是做這件事的方式,但如果你知道一些很酷的方法可以讓我使用foreach並保持'a'和'b'同步,請告訴我! :) – Dave 2010-11-20 08:18:45

+0

@Dave:絕對有這樣做的方法。將編輯。很高興聽到你有這本書的方式 - 希望你喜歡它!有疑問, – 2010-11-20 17:20:36