我正在研究一些代码并掌握这个概念,但我不确定如何在LINQ-to-objects中表达它。
我的情景是:
具有分层数据的树,可以使用拖放操作将某些项重新定位到其他父项。
我想支持拖动多个项目,树的示例如下:
层次结构中的每个视图模型项都是从我公开IReadOnlyList<Type>
的基本类型派生出来的,该基类型表明每个层次结构项目很乐意被重新定位为子项。
在PreviewDragEnter
事件中,我已经检查过每个被拖动的项目实际上都支持重新定位。
我实际想要解决的问题是如何检查每个至少1种类型的readonly列表,以便我可以确定每个被拖动的项目都可以重新定位到同一目标。
我意识到如果我从一个集合转到下一个集合,可以进行1-1 .Any()
检查,但是如何为任意数字执行此操作?
到目前为止,我有类似的东西,但我不确定它是否正确,它看起来不是最佳:
private void RadTreeView_PreviewDragStarted(object sender, Telerik.Windows.Controls.RadTreeViewDragEventArgs e)
{
var items = e.DraggedItems.Cast<HierarchyItemViewModel>();
// Every item being dragged must support being dragged
if (items.Any(i => i.ValidReorgTargets.Count == 0))
{
e.Handled = true;
return;
}
if (items.All(i => HasOneTypeInCommonWithOthers(i, items.Except(new[] { i }))))
{
e.Handled = true;
return;
}
}
private bool HasOneTypeInCommonWithOthers(HierarchyItemViewModel item, IEnumerable<HierarchyItemViewModel> others)
{
return others.All(i => i.ValidReorgTargets.Intersect(item.ValidReorgTargets).Any());
}
任何比这更好的东西都会非常感激。
答案 0 :(得分:1)
这应该有效:
if (items.Select(i => i.ValidReorgTargets).Aggregate((i1, i2) => i1.Intersect(i2)).Any())
{
e.Handled = true;
return;
}
换句话说,如果所有ValidReorgTargets
个集合中都有一个共同的交集,那么它们可以重新定位到同一个目标。
答案 1 :(得分:0)
(我本来会给你编译可编码的代码,但我不确定你的例子中的内容是什么,你将术语从实例更改为视图模型项到基类型到层次结构类型,只读列表到HierarchyViewItemModel和所以,只需按照文字说出来。)
枚举每个只读列表中的每个类型,累积到Dictionary&lt; type,int&gt;找到的每种类型的实例数。假设任何只读列表中没有重复项(您可以使用Distinct删除),那么字典中所有元素的键(其中累计值是您开始使用的只读列表的数量)就是您想要的类型。
累积字典是O(n),其中n是要添加到字典中的所有只读列表中的类型总数(从MSDN我们了解到Dictionary.Add是分摊的O(1)...或者可以是如果你在扩展字典时要小心一些),确定有值==你的只读列表数的类型(键)的数量是O(m),其中m是所有只读列表中不同类型的数量。因此,该算法在您的只读列表的所有元素的总大小上是线性的。