Reputation: 321
Is it possible to write this in LINQ? I tried using LINQ. However, I figured it will have to be looped twice; first to verify whether a
is present and next to iterate through 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.
I need to find unique Id belonging to a
.
I know there have been discussions on other threads but they were not helpful.
EDIT: Here's snippet of 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>
Upvotes: 2
Views: 3948
Reputation: 4218
If LINQ to XML will work for you then MarcinJuraszek's answer is perfect. To address your LINQ to Objects question, what about something like this?
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;
}
Upvotes: 3
Reputation: 43596
You should be able to use XDocument
to query your xml a bit easier
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.
Upvotes: -1
Reputation: 125620
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 toid
given as a method parameter. If element is not found method should returnnull
.
I think it can be done on the XML using Descendants()
method:
Let say, we have your XML loaded into a variable called doc
, which is an instance of XDocument
class.
var query= from a in doc.Descendants("a")
let i = (string)a.Element("Id")
where i == id
select a;
return query.FirstOrDefault();
Upvotes: 7
Reputation: 18031
Using LINQ to traverse things that references each other looks very hard to achieve to me. It would be easier if the q and a classes were merged together in a single one.
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;
}
Upvotes: 0