2013-02-07 43 views
1

我要寻找一个集合类用于以下情形:收集用于快速读取C#

  • 快速收集查找,每次一个项目。
  • 集合包含大约300 K项目。
  • 收集人群速度可能并不重要,但也非常快。
  • 没有更新/删除一次收集加载Ip2Location类型的项目将被填充到收藏

则需要使用/插入:

对收集
public class Ip2Location 
{ 
    public long IpFrom {get; set;} 
    public long IpTo {get; set;} 
    public string Country {get; set;} 
} 

IpFrom  IpTo  Country 
16909056 16909311 AU 
16909312 16941055 US 

项目查找通过完成一个指定的IP,像这样:

IpFrom < currentIp < IpTo 

任何想法,包括参考链接,将非常感激!

比较:HashSet, SortedSet

有没有更好的集合类?

参考: http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-fundamentals-choosing-the-right-collection-class.aspx

更新:使用Array.BinarySearch

问题:在下面的链接比较表

var index = Array.BinarySearch(ipCountries, new IpCountry { IpFrom = 16909056}, new Ip2LocationComparer()); 

它工作在排小数字,没有按在300k项目中工作(例如,索引是 - (totalrow + 1))。搜索项目被加载到300 K项目集合中。

 public class Ip2LocationComparer: IComparer<IpCountry> 
     { 
      public int Compare(IpCountry x, IpCountry y) 
      { 
       if (x != null && y != null) 
        return (x.IpFrom <= y.IpFrom && y.IpFrom <= x.IpTo)? 0 : -1; 

       return -1; 

      } 
     } 

更新2

我把它改成下面

public class Ip2LocationComparer: IComparer<IpCountry> 
      { 
       public int Compare(IpCountry x, IpCountry y) 
       { 
     if (x != null && y != null) 

      { 
       if (x.IpFrom > y.IpFrom) 
        return 1; 

       if (x.IpFrom < y.IpFrom) 
        return -1; 

       if (x.IpFrom == y.IpFrom) 
       { 
        if (y.IpFrom > x.IpTo) 
         return 1; 

        if (y.IpFrom < x.IpTo) 
         return -1; 

       } 

      } 

      return 0; 
} 

但是从二分查找该指数的回报仍然是nagtive,这是匹配的项目和后续项目之间的权利。例如如果我的搜索IpFrom是3,索引是在2和4之间。为什么它不返回2?我还没有测试IpTo场景。

任何想法,将不胜感激!

+0

您的搜索方法不起作用,因为您的比较器已损坏。如果x在“之前”y,则需要返回-1;如果x和y相同,则返回0;如果y在x之后,则返回1。在你的情况下,你几乎可以肯定希望实现是'x.IpFrom.CompareTo(y.IpFrom),如果结果为零,也返回'IpTo'比较(也是一个空检查)。这会给你第一个范围内的项目。然后继续下去,直到你点击一个项目,其中'to'范围在当前项目之前,然后完成。 – Servy

+0

感谢您的评论。我发布了更新2.请看看,任何想法将非常appreicated! – Pingpong

+0

你的比较器现在工作正常。你可以用更少的代码来完成,但是你所拥有的没有任何问题。 BinarySearch被设计为返回一个负值;只需查看MSDN上的方法和示例的文档即可查看它的正确用法。 – Servy

回答

4

您可以将其存储在数组中。

如果您在填充后对数组进行排序,那么BinarySearch将是查找currentIp落在哪里的非常快速的方式。

+0

谢谢!那么HashSet和SortedSet呢?你的意思是由IpFrom排序?因为IpFrom是唯一的。 – Pingpong

+0

不,你想要一个数组和二进制搜索你正在做的事情。哈希集合或排序列表必须查找,即使您可以遍历它们,它们也不会像二进制搜索那样具有性能。 –

+0

@Pingpong按照IpFrom排序的普通数组可以在IpFrom上进行二分搜索 –

0

数据结构明智,你可以尝试一个字典或排序列表,虽然有300000项,你可能会遇到问题。不过,我很好奇听到结果。使用BinarySearch的普通数组也可能不是一个错误的选项。

您也可以考虑利用机器上的所有核心进行快速查找。您可以在大多数分析器上使用.AsParallel() extension method,这些分析器将准备查询多个内核的集合。