简体   繁体   English

使用LINQ进行递归查询

[英]Recursive query using LINQ

Is it possible to write this in LINQ? 是否有可能在LINQ中写这个? I tried using LINQ. 我尝试使用LINQ。 However, I figured it will have to be looped twice; 但是,我认为它必须循环两次; first to verify whether a is present and next to iterate through qs . 首先验证a是否存在,然后迭代qs

So I came up with this code. 所以我提出了这个代码。

public a Traverse(List<q> qs,string id)
    {

        foreach (var q in qs)
        {
            if (q.as.Any(a => a.Id == id))
            {
                return q.as.First(a => a.Id == id);

            }

            foreach (var a in q.as)
            {
                var result =Traverse(a.qs, id);
                if(result != null)
                  return result;
            }
        }
        return null;
    }  

I am reading it from XML which is like "q" have "a" and "a" have "q" in recursive manner. 我正在从XML中读取它,就像“q”具有“a”和“a”以递归方式具有“q”。

I need to find unique Id belonging to a . 我需要找到属于a唯一ID。

I know there have been discussions on other threads but they were not helpful. 我知道有其他线程的讨论,但他们没有帮助。

EDIT: Here's snippet of XML 编辑:这是XML的片段

  <qs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <qs>
    <q>q 1</q>
    <Id>1</Id>
    <as>
      <a>
        <aprop>a</aprop>
        <Id>a 1.1</Id>
        <qs>
          <q>
            <q>q 1.1.1</q>
            <Id>1.1.1</Id>
            <as>
              <a>
                <a>a</a>
                <Id>a 1.1.1.1</Id>
                <qs />
                <type>1</type>
              </a>
              <a>
                <a>a</a>
                <Id>a 1.1.1.2</Id>
                <qs />
                <type>1</type>
              </a>
            </as>
          </q>
          <q>
            <q>q 1.1.2</q>
            <Id>1.1.2</Id>
            <as>
              <a>
                <a>a</a>
                <Id>a 1.1.2.1</Id>
                <qs />
                <type>1</type>
              </a>
              <a>
                <a>a</a>
                <Id>a 1.1.2.2</Id>
                <qs />
                <type>1</type>
              </a>
            </as>
          </q>

I'm not sure what you're really going to achieve. 我不确定你真正要实现的目标。 That's how I understand the problem: 这就是我理解这个问题的方法:

We are looking for <a> tag, that contains another tag named <Id> with value equals to id given as a method parameter. 我们正在寻找<a>标签,其中包含另一个名为<Id>标签,其值等于作为方法参数给出的id If element is not found method should return null . 如果未找到element,则方法应返回null

I think it can be done on the XML using Descendants() method: 我认为可以使用Descendants()方法在XML上完成:

Let say, we have your XML loaded into a variable called doc , which is an instance of XDocument class. 假设我们将您的XML加载到名为doc的变量中,该变量是XDocument类的一个实例。

var query= from a in doc.Descendants("a")
           let i = (string)a.Element("Id")
           where i == id
           select a;

return query.FirstOrDefault();

If LINQ to XML will work for you then MarcinJuraszek's answer is perfect. 如果LINQ to XML对你有用,那么MarcinJuraszek的答案是完美的。 To address your LINQ to Objects question, what about something like this? 要解决你的LINQ to Objects问题,那么这样的事情呢?

    public a Traverse(IQueryable<q> qList, string id)
    {
        return this.GatherAs(qList).FirstOrDefault(a => a.Id == id);
    }

    public IQueryable<a> GatherAs(IQueryable<q> qList)
    {
        IQueryable<a> aList = qList.SelectMany(q => q.aList);

        if (aList.Count != 0)
            aList = aList.Union(this.GatherAs(aList.SelectMany(a => a.qList)));

        return aList;       
    }

Using LINQ to traverse things that references each other looks very hard to achieve to me. 使用LINQ遍历引用彼此的东西对我来说很难实现。 It would be easier if the q and a classes were merged together in a single one. 如果q和一个类在一个中合并在一起会更容易。

However, as a beginning, your function can be simplified this way : 但是,作为开头,您的功能可以通过以下方式简化:

public a Traverse(List<q> qs, string id)
{
    foreach (var q in qs)
    {
        foreach (var a in q._as)
        {
            if (a.Id == id)
                return a;
            else
                return Traverse(a.qs, id);
        }
    }
    return null;
}

You should be able to use XDocument to query your xml a bit easier 您应该能够使用XDocument更轻松地查询xml

Example: 例:

  XDocument xdoc = XDocument.Load("c:\\MyXmlFile.xml");
  var results = xdoc.Descendants("a").Descendants("Id").Select(id => id.Value);

Returns all the Id values from a elements. 返回所有Id从值a元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM