Как мне выполнить запрос linq, чтобы найти поля в наборе данных, которые присутствуют в каждой записи набора?

#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>»).