C#实现选择题答案匹配的代码完善与优化咨询
Hey there! Let's fix up that answer matching logic and also look at some cleaner, more scalable ways to do this.
First: Finishing Your Original Approach
Your initial if-else structure works for basic cases, but we need to adjust it to properly handle the option lines and avoid edge cases. First, make sure you're splitting the full question string into individual lines, then check each option line properly (note the a. instead of just a to avoid false matches):
string questionContent = "1. The word 'virile' means what?\na. Like a rabbit\nb. Like a man\nc. Like a wolf\nd. Like a horse\n"; string targetAnswer = "Like a man"; // Split into lines and remove empty entries var lines = questionContent.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines.Skip(1)) // Skip the question line itself { if (line.StartsWith("a.") && line.Contains(targetAnswer)) { Reply("a"); break; // Exit loop once we find the match } else if (line.StartsWith("b.") && line.Contains(targetAnswer)) { Reply("b"); break; } else if (line.StartsWith("c.") && line.Contains(targetAnswer)) { Reply("c"); break; } else if (line.StartsWith("d.") && line.Contains(targetAnswer)) { Reply("d"); break; } }
This completes your original logic, but it's not the most flexible if you ever have more options (like e, f) or slightly different formatting.
Better: Scalable Approach with LINQ
For a cleaner, more maintainable solution, we can parse each option into a structured object and use LINQ to find the match. This works even if you add more options later without rewriting the entire condition block:
string questionContent = "1. The word 'virile' means what?\na. Like a rabbit\nb. Like a man\nc. Like a wolf\nd. Like a horse\n"; string targetAnswer = "Like a man"; var lines = questionContent.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); // Parse each option line into letter and content var matchingOption = lines.Skip(1) .Select(line => new { OptionLetter = line.Split('.')[0].Trim(), AnswerText = line.Substring(line.IndexOf('.') + 1).Trim() }) // Use OrdinalIgnoreCase if you want case-insensitive matching .FirstOrDefault(option => option.AnswerText.Equals(targetAnswer, StringComparison.Ordinal)); if (matchingOption != null) { Reply(matchingOption.OptionLetter); } else { Reply("Answer not found in options"); }
Even More Robust: Regex Matching
If you need to handle variations in option formatting (like extra spaces, or a) instead of a.), regular expressions are a great tool. This ensures you reliably extract the option letter and answer content regardless of minor formatting differences:
using System.Text.RegularExpressions; string questionContent = "1. The word 'virile' means what?\na. Like a rabbit\nb. Like a man\nc. Like a wolf\nd. Like a horse\n"; string targetAnswer = "Like a man"; // Regex to match lines starting with a letter (a-d), followed by . or ), then the answer Regex optionPattern = new Regex(@"^([a-d])[\.\)]\s*(.*)$", RegexOptions.Multiline); var match = optionPattern.Matches(questionContent) .Cast<Match>() .FirstOrDefault(m => m.Groups[2].Value.Equals(targetAnswer, StringComparison.Ordinal)); if (match != null) { Reply(match.Groups[1].Value); } else { Reply("Answer not found"); }
Each of these approaches has its place: stick with the if-else for super simple cases, use LINQ for readability and scalability, and regex when you need to handle flexible formatting.
内容的提问来源于stack exchange,提问作者rami_ahmed

