C# c中比较对象的最快方法#
我正在编写一个验证某些城市的应用程序。验证的一部分是通过匹配国家代码和cityname(或alt cityname)来检查城市是否已经在列表中 我将现有城市列表存储为:C# c中比较对象的最快方法#,c#,performance,C#,Performance,我正在编写一个验证某些城市的应用程序。验证的一部分是通过匹配国家代码和cityname(或alt cityname)来检查城市是否已经在列表中 我将现有城市列表存储为: public struct City { public int id; public string countrycode; public string name; public string altName; public int timezoneId; } List<City&
public struct City
{
public int id;
public string countrycode;
public string name;
public string altName;
public int timezoneId;
}
List<City> cityCache = new List<City>();
这对于很多记录来说是非常缓慢的,因为我也以同样的方式检查其他对象,如机场和国家。我有没有办法加快速度?这种比较是否有比List更快的集合,是否有比FirsOrDefault()更快的比较函数
编辑
我忘记发布我的Like()函数:
bool Like(string s1, string s2)
{
if (string.IsNullOrEmpty(s1) || string.IsNullOrEmpty(s2))
return s1 == s2;
if (s1.ToLower().Trim() == s2.ToLower().Trim())
return true;
return Regex.IsMatch(Regex.Escape(s1.ToLower().Trim()), Regex.Escape(s2.ToLower().Trim()) + ".");
}
我会为CityString和CountryCode使用哈希集。 差不多
var validCountryCode = new HashSet<string>(StringComparison.OrdinalIgnoreCase);
if (validCountryCode.Contains(city.CountryCode))
{
}
var validCountryCode=新哈希集(StringComparison.OrdinalIgnoreCase);
if(validCountryCode.Contains(city.CountryCode))
{
}
等等
我个人会在构造函数中进行所有验证,以确保只有有效的城市对象存在
其他需要注意的事项
var cityCache = new Dictionary<string, Dictionary<string, int>>();
var countryCode = "";
var cityCode = "";
var id = x;
public static IsCityValid(City c)
{
return
cityCache.ContainsKey(c.CountryCode) &&
cityCache[c.CountryCode].ContainsKey(c.CityCode) &&
cityCache[c.CountryCode][c.CityCode] == c.Id;
}
var cityCache=new Dictionary();
var countryCode=“”;
var cityCode=“”;
var id=x;
公共静态IsCityValid(c市)
{
返回
cityCache.ContainsKey(c.CountryCode)&&
cityCache[c.CountryCode]。ContainesKey(c.CityCode)&&
cityCache[c.CountryCode][c.CityCode]==c.Id;
}
编辑2
我不认为我必须解释这一点,但根据评论,也许
FirstOrDefault()
是一个O(n)操作。基本上,每次你试图在列表中查找某个内容时,你可以是幸运的,它是列表中的第一个,也可以是不幸的,它是列表的最后一个平均值。计数/2。另一方面,字典将是O(1)查找。使用IEqualtiyComparer,它将生成一个HashCode(),并查找它所在的bucket。如果只有大量的碰撞,那么它将使用Equals在同一个bucket中的事物列表中查找您要查找的内容。即使HashCode()质量很差(总是返回相同的HashCode),因为字典
/哈希集
使用素数存储桶,您也会将列表拆分,从而减少需要完成的相等数
因此,列出10个对象意味着您平均运行了5次。
一个包含以下10个相同对象的字典(取决于哈希代码的质量),可以是一个
HashCode()
调用,然后是一个Equals()
调用。这听起来像是一个很好的二叉树候选
有关.NET中的二叉树实现,请参阅:
编辑:如果您想快速搜索一个集合,并且该集合特别大,那么最好的选择是对其进行排序,并基于该排序实现搜索算法 当您希望快速搜索并相对不频繁地插入项目时,二叉树是一个很好的选择。不过,为了保持搜索速度,您需要使用平衡二叉树 不过,要使其正常工作,您还需要一个用于城市的标准密钥。数字键最好,但字符串也可以很好地工作。如果您将城市与其他信息(如州和国家)连接起来,您将获得一个很好的唯一密钥。您还可以将大小写更改为全部大写或小写,以获得不区分大小写的密钥 如果没有密钥,则无法对数据进行排序。如果您不能对数据进行排序,那么就不会有很多“快速”选项 编辑2:
我注意到Like函数经常编辑字符串。编辑字符串是一项极其昂贵的操作。最好在首次加载数据时执行一次
ToLower()
和Trim()
函数。这可能会大大加快您的功能。我认为您最大的性能问题是使用之类的操作符,这很昂贵。你不能简单地使用一个相等比较器吗?你能告诉我们你是如何调用这个比较方法的吗?出于几个原因,我建议不要在内存中这样做。首先是因为您已经看到这种机制存在明显的性能问题,但第二是因为您在内存中保存了大量信息,只是为了搜索它。这在数据库服务器上非常合适,往返费用非常小。是否有一个城市的cannonical表示?正如M Afifi所说,哈希集会快得多。但是,您需要注意的是,名称的任何细微变化都应该对应于同一个城市。@Mike-我在问题或评论中没有看到任何提到数据库的地方。为什么假设有一个附加的数据库?请注意,代码使用Like运算符-除非发生更改,否则此代码将无法工作。通过将正确的IEqualityComparer传递到字典中,可以轻松修复此问题。如果实现正确,ContainsKey将与您所追求的匹配。因此,如果您在那里实现类似的操作,您就不会解决性能问题-是吗?这显然是一个非常大的数据集,因此进行类似操作需要扫描,如果是直接相等的,则还有其他选项,如二进制搜索等。如果需要类似的功能-让数据库引擎来做,因为它适合它。。。不,你错了。他在很多方面都付出了代价,值得作为编辑添加。我决定使用你的方法,使用字典。我决定使用字典,这样我就可以轻松地搜索外部字符串键(国家代码)和内部字符串键(城市名称)的精确匹配。如果那些检查
var cityCache = new Dictionary<string, Dictionary<string, int>>();
var countryCode = "";
var cityCode = "";
var id = x;
public static IsCityValid(City c)
{
return
cityCache.ContainsKey(c.CountryCode) &&
cityCache[c.CountryCode].ContainsKey(c.CityCode) &&
cityCache[c.CountryCode][c.CityCode] == c.Id;
}