2009-09-01 43 views
1

我創建了一個範圍類型:範圍使用LINQ和字典

public class Range<T> where T : IComparable<T> 
{ 
    public Range(T min, T max) : this(min, max, false) { } 
    public Range(T min, T max, bool upperbound) 
    { 
    } 
    public bool Upperbound { get; private set; } 
    public T Min { get; private set; } 
    public T Max { get; private set; } 
    public bool Between(T Value) 
    { 
     return Upperbound ? (Min.CompareTo(Value) < 0) && (Value.CompareTo(Max) <= 0) : (Min.CompareTo(Value) <= 0) && (Value.CompareTo(Max) < 0); 
    } 
} 

我想在字典以此爲重點,讓我做基於範圍的搜索。是的,範圍可以重疊或可能存在差距,這是設計的一部分。它看起來很簡單,但我希望搜索更容易一些!我想比較一個範圍和它的T型值,所以我可以使用:myRange == 10而不是myRange.Between(10)。

怎麼樣? :-) (不想打破我的頭,我可能會找到答案,但也許我正在重新發明輪子或其他)


我想用這本字典做什麼?那麼,一般來說,我將使用範圍本身作爲一個關鍵。範圍將不僅僅用於字典。我正在處理大量具有最小/最大範圍的數據,並且我需要根據相同的最小/最大值對這些數據進行分組。字典中的值是這些產品的列表,它們都具有相同的範圍。通過使用範圍,我可以快速找到需要添加產品的正確列表。 (或者,如果未找到列表,請創建一個新條目。)

一旦我有按範圍分組的產品列表,我可以開始搜索在特定範圍內的值。基本上,這可能是一個Linq查詢字典中的所有值,其中提供值在最小值和最大值之間。

我實際上正在處理兩個這樣的列表。其中一個範圍是上限和另一個下限。可能會有更多這樣的列表,我首先需要根據範圍收集數據,然後查找其中的特定項目。

我可以使用List嗎?可能吧,但是我不會根據範圍本身對我的數據進行獨特的分組。清單列表呢?可能的,但是我再次考慮了詞典。 :-)


範圍示例:我有多個項目,範圍爲0到100.範圍爲0到1,1到2,2到3等的其他項目。範圍爲0到4,4到6的其他項目,6到8等。我甚至有0到0.5,0.5到1,1到1.5等等的項目。所以,首先我會根據它們的範圍對所有項目進行分組,所以範圍爲1到2的所有項目都會在一個列表中,而範圍爲0到100的所有項目將在不同的列表中。我已經計算過,我將處理大約50個可以相互重疊的不同範圍。但是,我有超過25000項需要這樣分組。

接下來,我從另一個來源獲得一個值。例如,我需要找到的值爲1.12。所以這次我使用Linq來搜索字典來查找所有的項目列表,其中1.12將在鍵的範圍內。因此,我會發現範圍1到2,1到1.5甚至0到100.在這些範圍後面會列出我需要爲這個值處理的項目。然後我可以前進到下一個值,大約有4000個不同的值。最好一切都應該以5秒完成。

+0

如果你的範圍重疊,這意味着一個值可以在兩個範圍在同一時間,不是嗎?在這種情況下,使用Dictionary不是一個真正的選項......至少不是System.Collections.Generic中的字典(TKey,TValue)。 – 2009-09-01 14:52:44

+0

除非您先將重疊範圍合併... – 2009-09-01 14:54:17

+0

是的,兩個範圍可以重疊。但是我想搜索一個確切的範圍,或者做一個foreach來查找指定值在範圍內的任何項目。但通常,我會搜索確切的範圍。 – 2009-09-01 15:03:17

回答

6

在字典中使用密鑰是重寫GetHashCodeEquals的問題。基本上你會根據最小值和最大值以及Upperbound創建一個散列。通常,您撥打的每個組件GetHashCode並將它們組合,例如:

public override int GetHashCode() 
{ 
    int result = 17; 
    result = result * 31 + Min.GetHashCode(); 
    result = result * 31 + Max.GetHashCode(); 
    result = result * 31 + Upperbound ? 1 : 0; 
} 

還會需要平等的測試。

雖然我不確定您的意思是「允許我根據範圍進行搜索」。你能否給出一些示例代碼來說明你想如何使用這種能力?我不完全相信它會適用於正常的字典方法......

我建議你不要重載==運算符允許你做一個遏制測試,但它。範圍不是等於該範圍中的值,因此使用該值的代碼不會非常直觀。

(我個人命名BetweenContains爲好。)

+0

覆蓋==運算符甚至不是一個選項,因爲兩個操作數都需要是相同的類型 – 2009-09-01 14:54:11

+0

@darin:不,它們不是(它超載,而不是重寫順便說一句)。我剛剛用'public static bool operator ==(Test x,string y)'編譯代碼,沒有任何問題 – 2009-09-01 15:06:34

+1

Jon是對的,用這種方式濫用平等是很奇怪的,如果你有等式運算符與我們直覺的平等性如何相似,A == B,B == C意味着A == C,我認爲在「範圍」示例中並不是這樣。 – 2009-09-01 15:30:55