我有以下结构:
Node
{
List<String> rootData;
List<Node> Children;
}
和
的集合List<Node> lstOfTrees
第一个Structure在rootData上保留了一些单词,(节点列表在这里并不重要),集合 lstOfTrees 包含树。
问题是: 在 lstOfTrees 中,有多个树。一些树具有其他树的rootData的子集(可能,不一定)。我想保持树在lstOfTrees中具有超集的其他rootData(子集应该被忽略)。
例如: 假设,lstOfTrees包含树
1: {rootData: A, B, C, D}
2: {rootData: E, F, G}
3: {rootData: G, H}
4: {rootData: J, A, C}
5: {rootData: D, Z}
我需要的最终答案应该是一个包含以下内容的新列表:
1: {rootData: A, B, C, D}
2: {rootData: E, F, G}
这可以使用LINQ和TPL(或更有效的方式)来完成吗?我希望它高效而正确。
修改
如果以下代码在所有情况下都能正常工作,或者我错过了什么?
lstOfTrees.Add(new node());
lstOfTrees[0].rootData = new List<string> {"A", "B", "C", "D"};
lstOfTrees.Add(new node());
lstOfTrees[1].rootData = new List<string> {"E", "F", "G"};
lstOfTrees.Add(new node());
lstOfTrees[2].rootData = new List<string> {"G", "H"};
lstOfTrees.Add(new node());
lstOfTrees[3].rootData = new List<string> {"J", "A", "C"};
lstOfTrees.Add(new node());
lstOfTrees[4].rootData = new List<string> {"D", "Z"};
Dictionary<int,node> dictOfTrees_indexToNode = Enumerable.Range(0, lstOfTrees.Count).ToDictionary(x=>x,x => lstOfTrees[x]);
List<int> notToInclude = new List<int>();
for (int i = 0; i < lstOfTrees.Count; i++)
{
for (int j = 0; j < lstOfTrees.Count; j++)
{
if (j != i)
{
if (!lstOfTrees[j].Equals(lstOfTrees[i]))
{
if (lstOfTrees[j].rootData.Join(lstOfTrees[i].rootData, root => root, innerRoot => innerRoot,
(root, innerRoot) => 1).Any())
{
bool test = (lstOfTrees[j].rootData.Count > lstOfTrees[i].rootData.Count);
notToInclude.Add(test ? i : j);
}
}
}
}
}
List<node> finalList = new List<node>();
finalList.AddRange(lstOfTrees.Except(notToInclude.Select(s=>dictOfTrees_indexToNode[s])));
另外,我可以改进吗?
答案 0 :(得分:1)
我已经简化了案例,只是为了测试只搜索字符串列表的列表,这应该是你在一个小的中间步骤之后所做的事情:
var list = lstOfTrees.Select(x => new HashSet<string>(x.rootData)).ToList();
此外,最好在这里使用集合,至少我没有在示例数据中看到任何重复,这是第二次更改。
在这里使用集非常重要,所以如果数据实际上可以在列表中重复,那么整个解决方案就必须改变。
结果如下:
var list = new List<List<string>> {
new List<string> {"A", "B", "C", "D"},
new List<string> {"E", "F", "G"},
new List<string> {"G", "H"},
new List<string> {"J", "A", "C"},
new List<string> {"D", "Z"}};
var sets = list.Select(x => new HashSet<string>(x)).ToList();
var result = sets.Select(x => sets.Where(y => x.Overlaps(y)) // You are looking not for 'subsets', but overlapping sets
.OrderByDescending(y => y.Count)
.FirstOrDefault())
.Distinct();
这会返回IEnumerable<HashSet<string>>
:
{“A”,“B”,“C”,“D”},{“E”,“F”,“G”}
在LINQPad中测试:)