使用LINQ进行递归查询

时间:2013-02-20 20:18:07

标签: c# linq

是否可以在LINQ中编写?我尝试使用LINQ。但是,我认为它必须循环两次;首先验证a是否存在,然后验证是否qs迭代。

所以我想出了这段代码。

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

我正在从XML中读取它 “q”以递归方式具有“a”和“a”具有“q”。

我需要找到属于a的唯一身份证。

我知道有其他线程的讨论,但它们没有帮助。

编辑:这是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>

4 个答案:

答案 0 :(得分:7)

我不确定你真正要实现的目标。这就是我如何理解这个问题:

  

我们正在寻找<a>标记,其中包含另一个名为<Id>的标记   值等于id作为方法参数给出。如果元素是   找不到方法应返回null

我认为可以使用Descendants()方法在XML上完成:

假设我们将您的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();

答案 1 :(得分:3)

如果LINQ to XML对您有用,那么MarcinJuraszek的答案是完美的。要解决你的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;       
    }

答案 2 :(得分:0)

使用LINQ遍历引用彼此的内容对我来说很难实现。如果将q和一个类合并在一起,将会更容易。

但是,作为开头,您的功能可以通过以下方式简化:

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

答案 3 :(得分:-1)

您应该可以使用XDocument来更轻松地查询xml

示例:

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

返回Id元素中的所有a值。