sab669
sab669

Reputation: 4104

How to filter a string[] with LINQ?

I have the following code:

string[] projects = Directory.GetDirectories(dir, "*", SearchOptions.TopDirectoryOnly);
string[] issues = Directory.GetFiles(dir, "*.txt", SearchOptions.AllDirectories)

foreach (string project in projects)
{
    var filteredIssues = from fi in issues where fi.Contains(project) select new { f = fi };

    foreach(string issue in filteredIssues)
    {
        // do something
    }
}

But this won't compile and gives me the following error:

Cannot convert type 'AnonymousType#1' to 'string'

I was looking at this example: http://www.dotnetlearners.com/linq/linq-to-string-array-with-example.aspx

And this SO question: How do I use LINQ Contains(string[]) instead of Contains(string)

But I wasn't really sure what uid is in that particular case or how to apply the solution to my problem.

I also tried

var filteredIssues = issues.Select(x => x.Contains(project)).ToArray();

But that returns an array of bools.

dir points to a "Projects" folder which will contain N uniquely named folders. Each folder there will contain an "Active" and "Archived" folder containing however many text files (which is what issues contains, and I'm effectively just trying to filter issues on a Project basis to load them into the UI grouped by project)

Ultimately I want the LINQ equivalent of this SQL statement:

SELECT issue FROM issues WHERE issue LIKE '%project%'

Although now as I'm writing this I realize I can just simply do string[] issues = Directory.GetFiles(project, "*.txt", SearchOptions.AllDirectories) from within the first foreach loop rather than outside. But I'm still curious how you could filter a collection of strings based on values that contain another value.

Upvotes: 3

Views: 9657

Answers (3)

Jodrell
Jodrell

Reputation: 35696

What you actually want is the text files not in the top level directory.

var projects = Directory.GetDirectories(dir, "*", SearchOptions.TopDirectoryOnly);
var issues = projects.SelectMany(p => 
        Directory.EnumerateFiles(p, "*.txt", SearchOptions.AllDirectories));
foreach(var issue in issues)
{
    // Do something;
}

Upvotes: 3

SimonGates
SimonGates

Reputation: 6111

You can use Where to filter a collection. Like so:

  var filteredIssues = issues.Where(x => x.Contains(project)).ToArray()

Select is for projecting one IEnumerbale<Type> to another IEnumerbale<Type2>. Think of it like Mapping, you can cherry pick what to map to the target type.

Upvotes: 4

sm.abdullah
sm.abdullah

Reputation: 1802

i think you should try this.

string[] projects = Directory.GetDirectories(dir, "*", SearchOptions.TopDirectoryOnly);
string[] issues = Directory.GetFiles(dir, "*.txt", SearchOptions.AllDirectories)

foreach (string project in projects)
{
    var filteredIssues = from fi in issues where fi.Contains(project) select fi;

    foreach(string issue in filteredIssues)
    {
        // do something
    }
}

you should select fi instead of select new { f = fi }; where select new { f = fi } is anonymous type with a string property name as f that is why anonymous type to string conversion failing..

Upvotes: 2

Related Questions