I have Dictionary<string, List<string>>
object. The Key
represents the name of a file and the Value
is a List<string>
which represents the names of certain methods in the file.
I loop over the dictionary and use the Key
to read in data from the file. I'm trying to then find lines in this file which contain an element from the Values
object:
static void FindInvalidAttributes(Dictionary<string, List<string>> dictionary)
{
//Get the files from my controller dir
List<string> controllers = Directory.GetFiles(controllerPath, "*.cs", SearchOption.AllDirectories).ToList<string>();
//Iterate over my dictionary
foreach (KeyValuePair<string, List<string>> entry in dictionary)
{
//Build the correct file name using the dictionary key
string controller = Path.Combine(ControllerPath, entry.Key + "Controller.cs");
if (File.Exists(controller))
{
//Read the file content and loop over it
string[] lines = File.ReadAllLines(controller);
for (int i = 0; i < lines.Count(); i++)
{
//loop over every element in my dictionary's value (List<string>)
foreach (string method in entry.Value)
{
//If the line in the file contains a dictionary value element
if (lines[i].IndexOf(method) > -1 && lines[i].IndexOf("public") > -1)
{
//Get the previous line containing the attribute
string verb = lines[i - 1];
}
}
}
}
}
}
There's got to be a cleaner way to implement the code inside the if (File.Exists(controller))
statement. I don't want to nest a foreach
inside of a for
, inside the parent-most foreach
.
Question: How can I determine if a string
contains any element in a List<string>
using LINQ?
Note that the two values are not identical; part of the string should contain the entire list element. I was able to find plenty of examples looking for the string inside the list elements, but that is not what I'm trying to do.
Example:
lines[0] = "public void SomeMethod()";
lines[1] = "public void SomeOtherMethod()";
List<string> myList = new List<string>();
myList.Add("SomeMethod");
myList.Add("AnotherMethod");
Using the above data, lines[0]
should result in my FindInvalidAttributes
method looking at the previous line because this string contains the first element in myList
. lines[1]
should not result in the method inspecting the previous line because SomeOtherMethod
does not appear in myList
.
Edit I'm very curious why this was downvoted and marked to be closed for being "too broad". I'm asking a tremendously specific question, provided my code, sample data and expected output for the sample data.
If you have lines
with all lines from the file and entry.Value
as the list of words to look for, then the following will return all lines containing at least one word from entry.Value
:
var result = lines.Where(l => l.Split(' ').Intersect(entry.Value).Any());
or more into your specific example:
var result =
lines.Where(l =>
l.Trim().StartsWith("public") && entry.Value.Any(l.Contains));
You can build up a regular expression that looks for all items in the list for the file in one shot.
Also, note that you're not using controllers
variable at all.
static void FindInvalidAttributes(Dictionary<string, List<string>> dictionary)
{
//Get the files from my controller dir
List<string> controllers = Directory.GetFiles(controllerPath, "*.cs", SearchOption.AllDirectories).ToList<string>();
//Iterate over my dictionary
foreach (var entry in dictionary)
{
//Build the correct file name using the dictionary key
string controller = Path.Combine(ControllerPath, entry.Key + "Controller.cs");
if (File.Exists(controller))
{
var regexText = "(?<attribLine>.*)\n" + string.Join("|", entry.Value.Select(t => "[^\n]*public\s[^\n]*" + Regex.Escape(t)))
var regex = new Regex(regexText)
//Read the file content and loop over it
var fileContent = File.ReadAllText(controller);
foreach (Match match in regex.Matches(fileContent))
{
// Here, match.Groups["attribLine"] should contain here what you're looking for.
}
}
}
}
I don't have input, so cannot easily test the code or the regex, but it should give the general idea for the approach and simplification.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.