#c# #linq #linq-to-xml #set-intersection
#c# #linq #linq-to-xml #множество-пересечение
Вопрос:
У меня есть набор данных XML с 10 тысячами записей, каждая из которых содержит набор полей.
Я хотел бы знать, какие поля должны быть нулевыми, а какие могут быть ненулевыми в схеме базы данных, которая соответствует набору данных.
Предлагает ли linq способ создания большого пересечения?
Пример:
<set>
<item>
<a/>
<foo />
<b/>
<c/>
</item>
<item>
<a/>
<foo />
<b/>
<c/>
</item>
<item>
<a/>
<b/>
</item>
<item>
<a/>
<foo />
<b/>
</item>
</set>
Прототип:
string[] CommonFieldNames(XElement[] elements)
{
// ...
}
Желаемый результат:
{ "a", "b" }
Ответ №1:
В приведенном ниже коде SelectedValue — это ваши ненулевые столбцы.
XDocument doc = XDocument.Parse("<set><item><a/><foo /><b/><c/></item><item><a/><foo /><b/><c/></item></set>");
var items =
doc.Descendants("item")
.Select(x=>x.Descendants().Select(y=>y.Name).ToList()).ToList();
var selectValue = items[0];
foreach (var item in items)
{
selectValue = selectValue.Intersect(item).ToList();
}
Ответ №2:
Вы могли бы использовать GroupBy и сравнить размер группы с общим количеством элементов:
XDocument doc = XDocument.Parse("<set><item><a/><foo /><b/><c/></item><item><a/><foo /><b/><c/></item><item><a/><b/></item><item><a/><foo /><b/></item></set>");
var items = doc.Document.Element("set").Elements("item");
var commonElementNames = items.SelectMany(x => x.Elements()) // Get all immediate children
.GroupBy(x => x.Name) // Group by name
.Where(g => g.Count() == items.Count()) // Filter for only those which show in every group.
.Select(g => g.Key.LocalName) // Select just the element names
;
Комментарии:
1. Хотя это не сработало бы в случае, когда у вас есть несколько дочерних элементов под узлом (например, «<a>» появляется дважды в «<item>»).