[英]How can I merge the results of a group by Linq-to-XML query?
我正在嘗試構造一個執行以下步驟的Linq-to-XML查詢:
到目前為止,我具有使用以下代碼的前兩個步驟。 請注意,MyGroupByKeyFunction的編寫方式可確保(除其他事項外)每個組中的所有元素都具有相同的深度(這就是orderby起作用的原因)。
var groups =
from e in doc.Root.Descendants()
group e by MyGroupByKeyFunction(e) into g
orderby g.First().Ancestors().Count() descending
select new {
agg = g.Aggregate(new List<XElement>(), (list, el) => {
list.Add(el);
return list;
}).Distinct(new MyCustomXElementEqualityComparer()),
items = g,
target = g.Last().Parent
};
最后兩個步驟是我陷入困境的地方。 我嘗試了以下方法,但是它並沒有按照我想要的方式工作。
foreach (var group in groups)
{
group.items.Remove();
foreach (var item in group.merge)
{
group.target.Add(item);
}
}
group.items中的元素已成功刪除並填充了目標,但我也希望在對group.items.Remove()的調用導致清空父元素的情況下,刪除group.items中元素的父元素。 因此,我嘗試用以下命令替換該行:
foreach (var delete in group.items)
{
if (delete.Parent.Elements().Count() == 1)
delete.Parent.Remove();
else
delete.Remove();
}
問題在於,此循環結果的連續迭代會導致NullReferenceException,因為父元素可能作為項目存在於原始查詢結果的另一個組中! 當然,這會導致delete.Parent為null,因為它先前已與XML樹分離。
我該如何解決這個問題?
更新資料
根據Falanor的建議,我嘗試將代碼修改為以下內容。 但是,這導致XDocument的最終結果僅包含根元素。 我不知道為什么會這樣。 有什么想法或更好的解決方案嗎?
HashSet<XElement> removed = new HashSet<XElement>();
foreach (var group in groups)
{
removed.UnionWith(group.items.Select(el => el.Parent).Where(el => !el.Parent.Equals(group.target)));
group.items.Remove();
foreach (var item in group.merge)
{
if (!removed.Contains(item))
group.target.Add(item);
}
}
removed.Where(el => el.Parent != null).Remove();
事實證明,Falanor的想法是正確的,我在編寫導致其無法使用的解決方案的方式時出現了一個小錯誤。 對UnionWith的方法調用應該是:
removed.UnionWith(group.items.Select(el => el.Parent).Where(el => !el.Equals(group.target)));
注意錯誤在where子句中。
此外,對於任何有興趣的人,我意識到我可以通過在初始查詢中添加以下“ where”子句(恰好在最終的“ select”語句之前)來大大減少代碼的執行時間:
where g.Select(p => p.Parent).Distinct().Count() > 1
這將導致查詢僅返回屬於不同父級的元素的分組。 只是為了透視起見,我針對我的代碼的XML文件返回了200,000多個分組。 加上附加的“ where”子句,分組數量下降到約150個! 最終結果是相同的。
也許刪除父母(以及孩子們)這樣做?
foreach (var group in groups)
{
if(group.Parent.Elements().Count() == 1)
group.Parent.Remove();
else
group.items.Remove();
foreach (var item in group.merge)
{
group.target.Add(item);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.