C
C#10mo ago
razeedazee

❔ .NET split string that is in a list

I have this (possibly horrible) code that works
private void buttonInstanceSearch_Click(object sender, EventArgs e)
{
string searchInfo = textBoxSearch.Text;
string searchDir = Directory.GetParent(AppContext.BaseDirectory).Parent.FullName + @"\instances";
listBoxSearch.Items.Clear();

var list_of_files_that_match = Directory.EnumerateFiles(searchDir, "README.md", SearchOption.AllDirectories).Where(delegate (string t)
{
return File.ReadAllText(t).Contains(searchInfo, StringComparison.CurrentCultureIgnoreCase);
}).ToList();

foreach (var value in list_of_files_that_match)
{
listBoxSearch.Items.Add(value);
}
}
private void buttonInstanceSearch_Click(object sender, EventArgs e)
{
string searchInfo = textBoxSearch.Text;
string searchDir = Directory.GetParent(AppContext.BaseDirectory).Parent.FullName + @"\instances";
listBoxSearch.Items.Clear();

var list_of_files_that_match = Directory.EnumerateFiles(searchDir, "README.md", SearchOption.AllDirectories).Where(delegate (string t)
{
return File.ReadAllText(t).Contains(searchInfo, StringComparison.CurrentCultureIgnoreCase);
}).ToList();

foreach (var value in list_of_files_that_match)
{
listBoxSearch.Items.Add(value);
}
}
The output is a list of full path to a file. I would like to split/remove the /README.md from the results. is this possible?
34 Replies
Angius
Angius10mo ago
So... you want to remove the last item in a list?
MODiX
MODiX10mo ago
Angius
REPL Result: Success
var path = @"C:/Documents/Unga/Bunga/Readme.md";
var list = path.Split('/');
var noLast = list[..^1];
string.Join('/', noLast)
var path = @"C:/Documents/Unga/Bunga/Readme.md";
var list = path.Split('/');
var noLast = list[..^1];
string.Join('/', noLast)
Result: string
C:/Documents/Unga/Bunga
C:/Documents/Unga/Bunga
Compile: 581.381ms | Execution: 77.383ms | React with ❌ to remove this embed.
razeedazee
razeedazee10mo ago
that looks like the result, the \README.md so i just have path.
Angius
Angius10mo ago
? You want just the path, without the file name? Use Path.DirectoryName() then
mtreit
mtreit10mo ago
.Where(delegate (string t)
.Where(delegate (string t)
harold
Angius
Angius10mo ago
var listOfMatchingFiles = Directory.EnumerateFiles(searchDir, "README.md", SearchOptions.AllDirectories
.Where(t => File.ReadAllText(t).Contains(searchInfo, StringComparison.CurrentCultureIgnoreCase)
.Select(Path.DirectoryName)
.ToList();
var listOfMatchingFiles = Directory.EnumerateFiles(searchDir, "README.md", SearchOptions.AllDirectories
.Where(t => File.ReadAllText(t).Contains(searchInfo, StringComparison.CurrentCultureIgnoreCase)
.Select(Path.DirectoryName)
.ToList();
First thing I noticed lol
mtreit
mtreit10mo ago
return File.ReadAllText(t).Contains(searchInfo, StringComparison.CurrentCultureIgnoreCase);
return File.ReadAllText(t).Contains(searchInfo, StringComparison.CurrentCultureIgnoreCase);
From an efficiency standpoint this also pains me, but I realize this question is probably not about optimizing performance.
razeedazee
razeedazee10mo ago
i am a NET noob, i am pasting away till things work with a poor grasp i need to the search the README.md files for a string and ideally list the parent dir.
MODiX
MODiX10mo ago
Angius
Use Path.DirectoryName() then
Quoted by
React with ❌ to remove this embed.
MODiX
MODiX10mo ago
Angius
REPL Result: Failure
Path.DirectoryName(@"C:/Documents/Unga/Bunga/Readme.md")
Path.DirectoryName(@"C:/Documents/Unga/Bunga/Readme.md")
Exception: CompilationErrorException
- 'Path' does not contain a definition for 'DirectoryName'
- 'Path' does not contain a definition for 'DirectoryName'
Compile: 336.801ms | Execution: 0.000ms | React with ❌ to remove this embed.
Angius
Angius10mo ago
umm
MODiX
MODiX10mo ago
Angius
REPL Result: Success
Path.GetDirectoryName(@"C:/Documents/Unga/Bunga/Readme.md")
Path.GetDirectoryName(@"C:/Documents/Unga/Bunga/Readme.md")
Result: string
C:/Documents/Unga/Bunga
C:/Documents/Unga/Bunga
Compile: 506.288ms | Execution: 34.826ms | React with ❌ to remove this embed.
Angius
Angius10mo ago
There
mtreit
mtreit10mo ago
If I actually had to do this I would probably shell out to ripgrep and parse the output (for performance reasons) but if you want to write it entirely in C# I would at least using a streaming reader instead of ReadAllText. Unless the set of files is always going to be so tiny it doesn't matter.
razeedazee
razeedazee10mo ago
i am using windows forms with net 7 via Visual Studio. the code optimisation thing is going to go over my head unless you ELI5 with examples.
mtreit
mtreit10mo ago
Eh, don't worry about it then. Get it working first.
mtreit
mtreit10mo ago
(For the record my approach would probably be something like this: https://paste.mod.gg/rfgcrmjmvucq/0) But again, don't optimize until you know you care about making it faster / use less memory.
BlazeBin - rfgcrmjmvucq
A tool for sharing your source code with the world!
razeedazee
razeedazee10mo ago
this seems to have worked, in regards to function
foreach (var value in list_of_files_that_match)
{
listBoxSearch.Items.Add(Path.GetDirectoryName(value));
}
foreach (var value in list_of_files_that_match)
{
listBoxSearch.Items.Add(Path.GetDirectoryName(value));
}
mtreit
mtreit10mo ago
cs is the language marker for C#
razeedazee
razeedazee10mo ago
thanks
razeedazee
razeedazee10mo ago
razeedazee
razeedazee10mo ago
@mtreit thanks for the example. i will try understand it
mtreit
mtreit10mo ago
Mainly it does two things for performance: 1. Enumerates the directories in parallel (which is why it uses a thread-safe collection to store the results) 2. Does not read the entire file into memory, but instead reads one line at a time. Probably in your case neither is important but as a pattern it's useful to know if you ever need to process very large files, or very large numbers of files, or both.
razeedazee
razeedazee10mo ago
it won't hurt to try and do it well. right now i'm just fumbling along with googles examples
mtreit
mtreit10mo ago
Oh the lineNumber thing can be ignored, I was originally storing that in the result but changed it when I saw you just wanted the directory name. Originally I was storing the file path and the line number where the first match was found.
razeedazee
razeedazee10mo ago
one thing i would like to know is how to make a function i reuse. i know how to do it in bash scripting. i have some repeated code i would function in bash but not sure how i do it in NET
private async void buttonYaesha_Click(object sender, EventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
dialog.InitialDirectory = Directory.GetParent(AppContext.BaseDirectory).Parent.FullName + @"\instances\yaesha";

if (dialog.ShowDialog() == DialogResult.OK)
{
selectedInstances = dialog.SelectedPath;
textBoxInstances.Text = dialog.SelectedPath;
}

if (File.Exists(dialog.SelectedPath + @"\README.md"))
{
await webView2Readme.EnsureCoreWebView2Async(null);
string yolo = Markdown.ToHtml(File.ReadAllText(dialog.SelectedPath + @"\README.md"));
webView2Readme.NavigateToString(yolo);

}

pictureBoxMiniMap.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBoxInfo.SizeMode = PictureBoxSizeMode.StretchImage;

if (File.Exists(dialog.SelectedPath + @"\info\mini-map.png"))
pictureBoxMiniMap.Image = Image.FromFile(dialog.SelectedPath + @"\info\mini-map.png");
else if (File.Exists(dialog.SelectedPath + @"\..\info\mini-map.png"))
pictureBoxMiniMap.Image = Image.FromFile(dialog.SelectedPath + @"\..\info\mini-map.png");
else
pictureBoxMiniMap.Image = null;

if (File.Exists(dialog.SelectedPath + @"\info\info.png"))
pictureBoxInfo.Image = Image.FromFile(dialog.SelectedPath + @"\info\info.png");
else if (File.Exists(dialog.SelectedPath + @"\..\info\info.png"))
pictureBoxInfo.Image = Image.FromFile(dialog.SelectedPath + @"\..\info\info.png");
else
pictureBoxInfo.Image = null;
}
private async void buttonYaesha_Click(object sender, EventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
dialog.InitialDirectory = Directory.GetParent(AppContext.BaseDirectory).Parent.FullName + @"\instances\yaesha";

if (dialog.ShowDialog() == DialogResult.OK)
{
selectedInstances = dialog.SelectedPath;
textBoxInstances.Text = dialog.SelectedPath;
}

if (File.Exists(dialog.SelectedPath + @"\README.md"))
{
await webView2Readme.EnsureCoreWebView2Async(null);
string yolo = Markdown.ToHtml(File.ReadAllText(dialog.SelectedPath + @"\README.md"));
webView2Readme.NavigateToString(yolo);

}

pictureBoxMiniMap.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBoxInfo.SizeMode = PictureBoxSizeMode.StretchImage;

if (File.Exists(dialog.SelectedPath + @"\info\mini-map.png"))
pictureBoxMiniMap.Image = Image.FromFile(dialog.SelectedPath + @"\info\mini-map.png");
else if (File.Exists(dialog.SelectedPath + @"\..\info\mini-map.png"))
pictureBoxMiniMap.Image = Image.FromFile(dialog.SelectedPath + @"\..\info\mini-map.png");
else
pictureBoxMiniMap.Image = null;

if (File.Exists(dialog.SelectedPath + @"\info\info.png"))
pictureBoxInfo.Image = Image.FromFile(dialog.SelectedPath + @"\info\info.png");
else if (File.Exists(dialog.SelectedPath + @"\..\info\info.png"))
pictureBoxInfo.Image = Image.FromFile(dialog.SelectedPath + @"\..\info\info.png");
else
pictureBoxInfo.Image = null;
}
i have a few buttons using same code except for different dirs i should be able to make a function here?
mtreit
mtreit10mo ago
Sure, making functions (methods) is a good practice. If you are using Visual Studio there is an "extract method" thing you can use to highlight the repeated code and turn it into a method
razeedazee
razeedazee10mo ago
thanks
mtreit
mtreit10mo ago
Also, use Path.Combine to combine paths and filenames, instead of string concatenation.
razeedazee
razeedazee10mo ago
@mtreit when i look at your example, why does my visual studio shwo this error
razeedazee
razeedazee10mo ago
razeedazee
razeedazee10mo ago
i kind of understand the error, but i don't get what solution is
mtreit
mtreit10mo ago
I wrote a stand-alone program that uses top-level statements - that code is inside a (compiler-generated) Main method that has a parameter named args, as most console programs do. If you're writing a GUI program it won't have that.
Accord
Accord10mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server
More Posts