在';和';和';或者';linq中的filter到c#中的xml

本文关键字:中的 xml 或者 linq filter | 更新日期: 2023-09-27 17:58:56

是否可以在linq to xml中将过滤器约束设置为"OR"?我在一个数组中进行迭代,以过滤所需的值,如下所示:

XElement root = XElement.Load(fileName);
IEnumerable<XElement> selectedElements = root.Elements("OrderNum").Elements("Job");
for (int i = 1; i < chkBx.Count(); i++)
{
    if (chkBx[i].Checked == true)
    {
        string element = "Diameter";
        string match = chkBx[i].Text;
        selectedElements = selectedElements.Where(el => (string)el.Parent.Element(element) == match);
    }
}

现在,过滤器将通过"AND"语句链接在一起。如果我想选择一个元素来统计这些筛选条件中的任何一个,该怎么办?

在';和';和';或者';linq中的filter到c#中的xml

var filters = chkBx.Where(r => r.Checked).Select(r => r.Text).ToList();
selectedElements = selectedElements.Where(r =>
      filters.Contains((string)r.Parent.Element(element)))

您有三个选项,具体取决于场景:

  • 您可以每次.Union查询(我怀疑这可能会产生大量开销)
  • 您可以构建一个自定义表达式(需要做大量工作,但实际上并不适合LINQ to Objects)
  • 你可以建立一个匹配的HashSet<string>(我的首选)

HashSet<string> matches = new HashSet<string>();
// this next bit can probably be simplified, perhaps using LINQ;
// left alone as it is orthogonal
for (int i = 1; i < chkBx.Count(); i++)   
 {
        if (chkBx[i].Checked == true)
        {
            string element = "Diameter";
            matches .Add(chkBx[i].Text);
        }
    }
var selectedElements = selectedElements.Where(el =>
      matches.Contains((string)el.Parent.Element(element)));

您可以通过两种方式来实现这一点,其中一种方式是使用表达式树构建表达式(对于IQueryable情况是必要的)。但是,由于您在查询内存中的模型,因此可以维护一个谓词列表,并使用Any扩展来进行筛选。

var predicates = new List<Func<XElement, bool>>();
for (int i = 1; i < chkBx.Count(); i++)
{
    if (chkBx[i].Checked)
    {
        var match = chkBx[i].Text;
        predicates.Add(el => (string)el.Parent.Element("Diameter") == match)
    }
}
selectedElements = selectedElements.Where(el => predicates.Any(p => p(el)));