考虑一个有3个级别的树:L1,L2,L3(但这只是一个特殊情况,为方便起见;每个级别的级别和子级数没有限制。)
每个级别都包含一个键和一个值(例如[string, integer]
)。
算法:如果直接子项都具有相同的值,则不要在子级别上显示这些值,而是在父级别上显示。 只有叶子可以有值,父母只根据叶子内容表示数据。
我的解决方案:我改变了主意。我需要一个通用的解决方案,不包括JFace LabelProvider
。我按顺序遍历树,并将值保存在地图中。我宁愿只保留没有 null 值的条目(即级别有东西要显示)。绩效至关重要。
Case 1 Case 2 Case 3 -------------- -------------- -------------- L1 | 1 L1 | - L1 | - |-- L2 | - |-- L2 | 1 |-- L2 | - | |-- L3 | - | |-- L3 | - | |-- L3 | 1 | +-- L3 | - | +-- L3 | - | +-- L3 | 2 +-- L2 | - +-- L2 | 2 +-- L2 | - |-- L3 | - |-- L3 | - |-- L3 | 1 +-- L3 | - +-- L3 | - +-- L3 | 2
<击>
限制:我一次只能访问一个级别,因为我正在使用内容和标签提供程序来填充树。例如,我有一个名为getColumnText(Object element, int columnsIndex)
的回调方法,其中element
是L1 / L2 / L3的实例,columnIndex
与值列重合。
我的解决方案:根据element
对象的实例,我向上和/或向下查看值是否为自杀。如果他们这样做,我不会在element
级别显示文本。代码特定于我的项目,因此我不能发布任何内容,因为它会使问题更难。但如果你坚持不懈,我可以写一个伪代码。
问题:我觉得这不是很优化(在每个getColumnText
调用上应用算法)。有没有机会推广这个算法?或者我应该将它移到标签提供者之外并将这些“值”保存在地图中?
击>
答案 0 :(得分:2)
初始化字典D
,我们将用它来存储结果。
假设我们在节点n
。按如下方式定义Value(n)
:
n
是叶节点,则返回其值。n
有子女c0, c1, .., c(k-1)
。firstChildValue = Value(c0)
。int i = 1, i <= k-1
执行以下操作:
firstChildValue == Value(ci)
,则不执行任何操作。firstChildValue != Value(ci)
:如果firstChildValue
非空,请将所有子c1, .., c{i-1}
添加到D
,其值为firstChildValue
。然后将每个孩子ci, .., c{k-1}
添加到具有所述值的非Value(ci)
到D
。 返回 null
,因为n
有不同价值观的孩子。firstChildValue
,因为所有孩子都有相同的价值。要执行此操作,请致电Value(root)
,并在root
为非空时将Value(root)
添加到字典中。
我认为这是你能做的最好的事情,因为它只评估每个节点一次,并且只将必要的节点添加到字典中。
E:感谢@GGrec帮助我调试这个。在与其他人分享之前,这是一种检查事物的教育。
答案 1 :(得分:1)
我认为你应该首先忽略性能。相反,尽量做到通用。编写两个不同的标签提供程序实现,它们不依赖于您的内部数据结构,但可以与其他ILabelProvider
和ITreeContentProvider
实例一起使用:
SummarizingLabelProvider
会在树上拉出常用标签,因此如果子树的叶子具有相同的标签,则会为此子树的所有节点返回此标签。
如果父母已经拥有相同的标签,IgnoreDetailsLabelProvider
将忽略子标签。
<强> SummarizingLabelProvider#getText(element)
强>
递归查看树的子项(使用内容提供程序):如果所有子项具有相同的文本,则返回此文本,否则返回元素的原始文本(使用其他标签提供程序)。需要另一个ILabelProvider
和ITreeContentProvider
作为构造函数参数。
<强> IgnoreDetailsLabelProvider#getText(element)
强>
如果其他标签提供程序返回元素及其父元素的相同文本,则返回null
。需要另一个ILabelProvider
和ITreeContentProvider
作为构造函数参数。
现在您可以链接您的标签提供商:
ILabelProvider lp1 = // original label provider
ILabelProvider lp2 = new SummarizingLabelProvider(contentProvider, lp1);
ILabelProvider lp3 = new IgnoreDetailsLabelProvider(contentProvider, lp2);
treeViewer.setLabelProvider(lp3);
<强>性能强>
性能最强的标签提供商是SummarizingLabelProvider
。对于每个getText(element)
,在最坏的情况下,它必须遍历element
的子树。您可以使用缓存以前计算的文本的Map
来优化它。但在这样做之前,你应该测试初始性能是否太低!
IgnoreDetailsLabelProvider
只会根据SummarizingLabelProvider
两次调用基础getText
,因此它也会从缓存中获利。