我有一个对象列表,我希望将其减少到仅包含属于单独列表的属性的对象。
List1是一个简单字符串列表。
List2是包含两个字符串属性的对象列表; A和B.
应删除List1中不存在A 和 B的所有项目。
此过程非常依赖于时间,需要尽可能快。 目前我有以下实施方式;
var List1 = new List<String>() {"Around", "9000", "strings"}; //List of about 9000 strings
var List2 = databaseList.ToList(); //Around 2.5 million objects
var reducedList = new HashSet<Object>();
foreach (var item in List2)
{
if(List1.Contains(item.A) && List1.Contains(item.B))
{
reducedList.Add(item);
}
}
此过程大约需要7秒钟才能完成,这对我目前的要求来说太慢了。
我尝试使用LINQ运行它,但是给出相同的结果,大约7秒。
var reducedList = List2.Where(r => List1.Contains(r.A)).Where(r => List1.Contains(r.B)).ToList();
有什么建议我可以做些什么来改善这个?
修改 我无法在SQL方面做到这一点,因为我需要比较的9000个字符串不能“翻译”到SQL查询中,但会超过我们的SQL Server中允许的允许2100输入参数设置。
答案 0 :(得分:3)
我没有尝试过,但可能会提高性能。
var List1 = new List<String>() {"Around", "9000", "strings"};
var List2 = databaseList.ToList(); //Around 2.5 million objects
var reducedList = List2.RemoveAll(i => !List1.Contains(i.A) && !List1.Contains(i.B)).ToList();
答案 1 :(得分:2)
首先,让我们更快地查找第一个列表:
var sought = new HashSet<String>() {"Around", "9000", "strings"};
如果你只是想要迭代它,为什么还要在内存中创建列表呢?除非您打算将List2
用于其他目的,否则它没有做任何事情。
foreach (var item in databaseList)
{
if(sought.Contains(item.A) && sought.Contains(item.B))
{
reducedList.Add(item);
}
}
同时将reducedList
哈希列表正确键入new HashList<TheActualTypeOfTheItemsHere>
。
如果该类型未实现IEquatable<T>
,则添加该实现。如果那是不可能的,那么创建一个适当的IEqualityComparer<T>
并在reducedList
的构造函数中使用它。
答案 2 :(得分:0)
正如@Ondrej Svejdar指出的那样,如果databaseList
来自EntityFramework,那么你不应该调用ToList()
,因为它会进行数据库查询,返回250万条记录
var reducedList = databaseList
.Where(r => List1.Contains(r.A) && List1.Contains(r.B))
.ToList();
如果List1
来自数据库(我希望9000是手动构建的大数字),那么请考虑使用join
运算符。
答案 3 :(得分:0)
您的数据库版本可能是个问题: 参考:Slower sqlite 由于我不知道你使用的是什么DB,这可能是“无用的”#34;。但是看看你的数据库是否有最新版本,看看它有多快。在另一台PC /浏览器/手机上测试你的程序,看看你是否得到相同的结果。
现在你应该找到确实花费很长时间的东西。尝试删除你的if语句,看看速度是否有所改善。如果它没有改进,那就是查询速度是一个问题。如果是这样,请尝试以您不需要使用的方式查询您的数据库。
答案 4 :(得分:0)
您可以尝试在对象上实现IEquatable
,因为这是Contains
将调用以查看对象是否在列表中的方法
有关详细信息,请参阅此post。
答案 5 :(得分:0)
List1通常有多大?如果它是您样本中的小列表,那么保留列表就可以了。如果情况并非如此,那么使用HashSet可能会获得更好的结果。
我认为真正的游戏规则改变者是避免使用250万个对象加载List2,以便稍后过滤它们。如果databaseList是某种类似于DbSet的IEnumerable,那么你可能会得到更好的结果:
var List1 = new List<String>() {"Around", "9000", "strings"};
var reducedList = (from item in databaseList
where List1.Contains(item.A) && List1.Contains(item.B)
select item).ToList();
对缩小列表使用HashSet只会减慢插入速度。如果您使用它来避免重复,或者为了加快后续查找,那么您应该保留它。否则List会更好。