Grouping Logical Operators (Multiple Sets of Conditions) in a do {} while () loop?
I currently have the following loop:
do {
checkedWord = articleWords.Dequeue().TrimEnd('?', '.', ',', '!');
correct = _spellChecker.CheckWord(checkedWord);
} while (correct && articleWords.Count > 0);
I am queuing up the words from an array that was split from a textbox with ' '
as the separator. The loop works fine, except for I don't want any blank entries ""
or really anything non alpha-numeric to stop the loop. Currently if there's more than one space between the words then the loop ends and it continues on to get word suggestions from the spellchecker.
If I do while (correct && articleWords.Count > 0 || checkedWord == "");
then it'll skip any blank queue entries, but it still hangs up on things like new lines - so if the textbox that it loads from contains a couple of paragraphs it screws up at the newline separating the two. I've also tried while (correct && articleWords.Count > 0 || !Char.IsLetterOrDigit(checkedWord, 0));
but that also doesn't work.
Question 1: Can you group conditions like (statement1 == true && count > 0) || (statement1 == false && Char.IsLetterOrDigit(char))
? - Meaning that all of the conditions in the first grouping must be met OR all of the conditions in the second set must be.
Question 2: I want my loop to continue progressing until an actual spelling error is found, and for it to ignore things like empty queue entries, as well as anything that's not an alpha-numeric character at the beginning of the string.
I suspect that I'm close with the Char.IsLetterOrDigit
bit, but have t开发者_如何学Goo figure out how to do it correctly.
Let me know if more info is required.
Thanks!
You should not use composite loop condition, a good practice is usage while loop with easy general condition and 'break' in loop body when you should leave it.
You can use some thing like this:
public void Test()
{
var separators = new[] { ' ', '\t', '\r', '\x00a0', '\x0085', '?', ',', '.', '!' };
var input = "Test string, news112! news \n next, line! error in error word";
var tokens = new Queue<string>(input.Split(separators, StringSplitOptions.RemoveEmptyEntries));
string currentWord = null;
while (tokens.Any())
{
currentWord = tokens.Dequeue();
if (currentWord.All(c => Char.IsLetterOrDigit(c)))
{
if (!CheckSpell(currentWord))
{
break;
}
}
}
}
public bool CheckSpell(string word)
{
return word != null && word.Length > 0 && word[0] != 'e';
}
If your goal is to find the first error, you can skip the while loop and do the following:
var firstError = tokens.Where(t => t.All(Char.IsLetterOrDigit) && !_spellChecker.CheckWord(t)).FirstOrDefault();
So long as you have a valid boolean expression, you can do that without an issue. This is something that is very easy to test.
To use
Char.IsLetterOrDigit
you will need to loop over each character in the string and test it.
When it comes to text selections you should use regular expressions. It is very powerfull and fast framework for text queries. It is capable of doing it's job with O(n) complexity. It helps you because you don't have to think how you will select your text values you just specify what you need
Try this code. The pattern part @"\w+" means that I want to select all groups of alphanumeric symbols whose length > 1. If I'd wanted to select all words that start with letter 't' than I would write @"t\w+".
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace Test
{
class Program
{
static void Main(string[] args)
{
string str = "The quick brown fox jumps over the lazy dog";
Regex regex = new Regex(@"\w+", RegexOptions.Compiled);
for (Match match = regex.Match(str); match.Success; match = match.NextMatch())
{
Console.WriteLine(match.Value);
}
}
}
}
Q1. Absolutely. Just make sure your groupings are properly separated.
Q2. For performance and clarity, I would use REGEX to clean your input before queuing:
using System.Text.RegularExpressions;
...
string input = GetArticle(); // or however you get your input
input = Regex.Replace(input, @"[^0-9\w\s]", string.Empty);
// not sure what your separators but you can always
// reduce multiple spaces to a single space and just split
// on the single space
var articleWords = new Queue<string>(input.Split( ... ));
do {
checkedWord = articleWords.Dequeue();
// put your conditional grouping here if you want
if(!_spellChecker.CheckWord(checkedWord)) {
// only update "correct" if necessary - writes are more expensive =)
// although with the "break" below you shouldn't need "correct" anymore
// correct = false;
// in case you want to raise an event - it's cleaner =)
OnSpellingError(checkWord);
// if you want to stop looping because of the error
break;
}
}
while(articleWords.Count > 0);
I wouldn't use Char.IsLetterOrDigit
as I think that would be slower...besides, with the REGEX in the beginning you should have taken care of the entries that aren't characters or digits.
EDIT Adding LINQ response
On second thought, I think you're just trying to find spelling errors so how about this?
using System.Text.RegularExpressions;
...
string input = GetArticle(); // or however you get your input
// clean up words from punctuation
input = Regex.Replace(input, @"[^0-9\w\s]", string.Empty);
// trim whitespace
input = Regex.Replace(c, @"\s+", @" ");
var errors = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).All(w => !_spellChecker.CheckWord(w));
Then you can just do whatever you want with the errors =) Or you can just use a .Any
if you just want to know whether there exists a spelling mistake at all.
Q1: Sure, it's possible to group conditions like that.
Q2: What about something like this?
string[] articleWords = textBoxText.Split(' ');
articleWords = articleWords.Select(a => a.Trim()).ToArray(); // remove all whitespaces (blanks, linebreaks)
articleWords = articleWords.Where(a => !string.IsNullOrEmpty(a)).ToArray(); // remove empty strings
bool correct = false;
bool spellingErrorFound = false;
for (int i = 0; i < articleWords.Length; i++)
{
string checkedWord = articleWords[i].TrimEnd('?', '.', ',', '!');
correct = _spellChecker.CheckWord(checkedWord);
if (!correct)
spellingErrorFound = true;
}
精彩评论