Mic*_*kus 6 .net c# linq progress distinct
我有一个名为的自定义对象数组AnalysisResult
.该数组可以包含数十万个对象; 并且,偶尔我只需要Distinct()
该数组的元素.所以,我写了一个调用的项比较器类,AnalysisResultDistinctItemComparer
并按我这样的方式调用:
public static AnalysisResult[] GetDistinct(AnalysisResult[] results)
{
return results.Distinct(new AnalysisResultDistinctItemComparer()).ToArray();
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,当数组特别大(大于200,000个对象)时,此调用可能需要很长时间(大约几分钟).
我目前在后台工作程序中调用该方法并显示一个旋转gif,以警告用户该方法正在执行,并且应用程序尚未冻结.这一切都很好,但它没有给用户任何当前进展的指示.
我真的需要能够向用户指出此动作的当前进度; 但是,我一直无法想出一个好方法.我正在玩这样的事情:
public static AnalysisResult[] GetDistinct(AnalysisResult[] results)
{
var query = results.Distinct(new AnalysisResultDistinctItemComparer());
List<AnalysisResult> retVal = new List<AnalysisResult>();
foreach(AnalysisResult ar in query)
{
// Show progress here
retVal.Add(ar);
}
return retVal.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
但问题是我无法知道我的实际进展是什么.思考?建议?
不要ToArray()
在方法末尾调用,只需使用yield return
. 所以这样做:
public static IEnumerable<AnalysisResult> Distinct(AnalysisResult[] results)
{
var query = results.Distinct(new AnalysisResultDistinctItemComparer());
foreach(AnalysisResult ar in query)
{
// Use yield return here, so that the iteration remains lazy.
yield return ar;
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,yield return
会执行一些编译器魔法来确保迭代保持惰性,因此您不必等待创建完整的新集合即可返回调用者。相反,在计算每个项目时,您会立即将该项目返回给消费者(然后消费者可以执行更新逻辑 - 如果需要的话,针对每个项目)。GetDistinct
您也可以在您的方法中使用相同的技术。
Jon Skeet 有一个如下所示的实现(特定属性上的 LINQ 的 Distinct()):
public static IEnumerable<TSource> DistinctBy<TSource, TKey>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> seenKeys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这里他使用了 a HashSet
,它的构建目的是不允许重复。只需检查该项目是否已添加,如果没有,则将其退回。
总而言之,请记住这是一个算法和数据结构类型的问题。这样做会容易得多:
Dictionary<Key, Value> distinctItems = new Dictionary<Key, Value>();
foreach (var item in nonDistinctSetOfItems) {
if (distinctItems.ConatainsKey(item.KeyProperty) == false) {
distinctItems.Add(item.KeyProperty, item);
}
}
... = distinctItems.Values // This would contain only the distinct items.
Run Code Online (Sandbox Code Playgroud)
也就是说,符号表就是Dictionary
为了解决此类问题而构建的 - 将条目与唯一键相关联。如果您以这种方式存储数据,就会大大简化问题。不要忽视简单的解决方案!
归档时间: |
|
查看次数: |
201 次 |
最近记录: |