954,500 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Trying to move a step further in my LINQ knowledge

I've been working on something with alot of iteration (foreach) and now that everything is working I'd like to optimize it by changing it to link. Currently I am trying to translate this foreach code to LINQ

int count = 0;
foreach( string file in Directory.GetFiles( path ))
{
        XDocument xdoc = new XDocument();
        xdoc = XDocument.Load( file );
         count += xdoc.Descendants( "PAGE" ).Count();
}


I'm not sure if it even possible however, here is the result of my trying :)

int count;
count = Directory.GetFiles( path ).Select( file => XDocument.Load( file ).Descendants( "PAGE" )).Select( result => result).Count() ;


I'd appreciate if someone could help but also explain me what's going on with the LINQ query.

Thank you =)

PierlucSS
Junior Poster
187 posts since Feb 2010
Reputation Points: 65
Solved Threads: 30
 

The first part of the query is retrieving the files in the given directory. The second part is a select projection that takes a given filename, loads an XDocument and retrieves all descendants of that document of a particular name. In terms of the delegate signature for the inner function, it would be

Func> func

As in a function that takes a string (file) and returns an IEnumerable of XElements.

Next, you're including what is currently an unnecessary Select call that simply takes an IEnumerable and returns the same IEnumerable.

Func, IEnumerable> func

And, lastly, you're retrieving the count of all elements in the IEnumerable>. But what you're getting is actually a count of the inner IEnumerable elements, not the count of the XElements.

To get the total count of your descendants, you could rewrite the statement to look something like this:

int sum = Directory.GetFiles(directoryPath)
            .Select(file => XDocument.Load(file).Descendants(descendantName).Count())
            .Sum();


Edit: Since I spelled out the other select functions, this one is taking a sting filename and returning an integer representing the count of descendants of a given name in the file.Func

And then, of course, you simply sum those integer results.

apegram
LINQ!
Team Colleague
552 posts since Jan 2010
Reputation Points: 327
Solved Threads: 135
 

The first part of the query is retrieving the files in the given directory. The second part is a select projection that takes a given filename, loads an XDocument and retrieves all descendants of that document of a particular name. In terms of the delegate signature for the inner function, it would be

Func> func

As in a function that takes a string (file) and returns an IEnumerable of XElements.

Next, you're including what is currently an unnecessary Select call that simply takes an IEnumerable and returns the same IEnumerable.

Func, IEnumerable> func

And, lastly, you're retrieving the count of all elements in the IEnumerable>. But what you're getting is actually a count of the inner IEnumerable elements, not the count of the XElements.

To get the total count of your descendants, you could rewrite the statement to look something like this:

int sum = Directory.GetFiles(directoryPath)
            .Select(file => XDocument.Load(file).Descendants(descendantName).Count())
            .Sum();

Of course it makes sens, I realise that if I had written this with an SQL query it would have ended up this way. What I am not understanding is that I didn't think about that :) Anyways, you are awesome man, thank you for your help with LINQ, really appreciated.

PierlucSS
Junior Poster
187 posts since Feb 2010
Reputation Points: 65
Solved Threads: 30
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: