Change between 'and' and 'or' filter in linq-to-xml in C #

Is it possible to set filter restrictions to "OR" in linq-to-xml? I iterate over the array to filter the desired values ​​as follows:

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);
    }
}

The filter will now be associated with the AND instruction. What if I want to select an item that satisfies any of these filter conditions?

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

You have three options, depending on the scenario:

  • you could .Unionask every time (which could cause a lot of overhead, I suspect)
  • you can create a custom expression (a lot of work and not very suitable for 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)));
+2

You can do this in two ways, one way is to create an expression using expression trees (necessary for IQueryable situations). But since you are querying the model in memory, you can save the list of predicates and use the extension Anyto filter.

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)));
+1
source

All Articles