I've been working on an OCR program that accepts a photo with text in it (in this specific case, a driver's license) as well as a first name and a last name as arguments.
Once the software reads the id photo, I search for the first and last name in the recognized text. Unfortunately, as the image quality can be pretty low, it will sometimes not get the name quite right.
Is there a way I could look for a SIMILAR needle in a haystack? That is, look for any occurrences that are similar to the first/last name? For example:
Needle: campbell
Haystack:
operaioxsllcence
gcltdriver
exries13NOV2020
carnpbeiljtttj
...
The string that would be close enough is "carnpbeil".
This is what I'm using now, and it only helps in very specific situations:
private bool SourceContains(string haystack, string needle)
{
bool ret = false;
if (haystack.Contains(needle) ||
haystack.Replace("l", "i").Contains(needle) ||
haystack.Replace("i", "l").Contains(needle) ||
haystack.Replace("0", "o").Contains(needle) ||
haystack.Replace("o", "0").Contains(needle) ||
haystack.Replace("j", "d").Contains(needle) ||
haystack.Replace("d", "j").Contains(needle) ||
haystack.Replace("i", "j").Contains(needle) ||
haystack.Replace("j", "i").Contains(needle) ||
haystack.Replace("e", "f").Contains(needle) ||
haystack.Replace("f", "e").Contains(needle) ||
haystack.Replace("r", "p").Contains(needle) ||
haystack.Replace("p", "r").Contains(needle) ||
haystack.Replace("s", "r").Contains(needle) ||
haystack.Replace("r", "s").Contains(needle) ||
haystack.Replace("r", "n").Contains(needle) ||
haystack.Replace("n", "r").Contains(needle) ||
haystack.Replace("k", "n").Contains(needle) ||
haystack.Replace("n", "k").Contains(needle) ||
haystack.Replace("h", "n").Contains(needle) ||
haystack.Replace("n", "h").Contains(needle) ||
haystack.Replace("k", "ll").Contains(needle) ||
haystack.Replace("ll", "k").Contains(needle) ||
haystack.Replace("ci", "d").Contains(needle) ||
haystack.Replace("d", "ci").Contains(needle) ||
haystack.Replace("cl", "d").Contains(needle) ||
haystack.Replace("d", "cl").Contains(needle) ||
haystack.Replace("m", "in").Contains(needle) ||
haystack.Replace("in", "m").Contains(needle) ||
haystack.Replace("rn", "m").Contains(needle) ||
haystack.Replace("m", "rn").Contains(needle)
)
{
ret = true;
}
return ret;
}
For each word in haystack calculate the levenshtein distance to needle. The word with the shortest distance is most likely to be your needle. Have a look at this question for implementations.
Related
I have a list of existing products presented in a datagridview. User can add new product using this window
Some of the fields can be accepted as empty. The text field must have char only and the int fields must have positive int only. ID, price, playtime and status must be positive ints. The rest must be chars, when they aren't empy that is. The code i have works but only when every field that could be empty is empty. It doesn't work if some are and others aren't.
It would also be nice if you could solve the issue of accepting empty int fields.myint.ToString().Length; is not getting the job done seems like. Maybe the answer is easy but I'm sorta new to C# and .Net.
Here is the code i wrote
if (!plist.type.Any() || !plist.author.Any() || !plist.genre.Any() || !plist.format.Any() || !plist.language.Any() || !plist.platform.Any())
{
if (plist.id != Math.Abs(plist.id) || plist.price != Math.Abs(plist.price)
|| plist.playtime != Math.Abs(plist.price) || plist.status != Math.Abs(plist.price))
{
DialogResult = DialogResult.No;
}
else if (plist.type.Any(char.IsDigit) || plist.name.Any(char.IsDigit)
|| plist.author.Any(char.IsDigit) || plist.genre.Any(char.IsDigit)
|| plist.format.Any(char.IsDigit) || plist.language.Any(char.IsDigit) || plist.platform.Any(char.IsDigit))
{
DialogResult = DialogResult.No;
}
else
{
DialogResult = DialogResult.OK;
}
}
else
{
DialogResult = DialogResult.OK;
}
Let me know if there is anything left to clear up.
I appreaciate any suggestions you got for me!
Assuming that type, author, genre, format, language and platform are mandatory fields, you should be setting DialogResult to DialogResult.No instead of OK in your bottom most else statement. Otherwise, you will be skipping your logic and returning the wrong result.
if (!plist.type.Any() || !plist.author.Any() || !plist.genre.Any() || !plist.format.Any() || !plist.language.Any() || !plist.platform.Any())
{
if (plist.id != Math.Abs(plist.id) || plist.price != Math.Abs(plist.price)
|| plist.playtime != Math.Abs(plist.price) || plist.status != Math.Abs(plist.price))
{
DialogResult = DialogResult.No;
}
else if (plist.type.Any(char.IsDigit) || plist.name.Any(char.IsDigit)
|| plist.author.Any(char.IsDigit) || plist.genre.Any(char.IsDigit)
|| plist.format.Any(char.IsDigit) || plist.language.Any(char.IsDigit) || plist.platform.Any(char.IsDigit))
{
DialogResult = DialogResult.No;
}
else
{
DialogResult = DialogResult.OK;
}
}
else
{
DialogResult = DialogResult.No;
}
As for the empty integer length issue, make sure that you are not trying to turn a null value to a string. Consider using a numericUpDown instead of a textbox as the numericUpDown is designed to work with numbers. You can even set limits to you numbericUpDown, like a lower number limit to prevent negative numbers.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.numericupdown?view=windowsdesktop-7.0
I am coding a selenium test case to verify all elements are present on a web page and Im fairly green at coding so bear with me here. I have boolean vars set up for each element and if not found, I mark them false. At the end of my code/test, I want to display custom exceptions for each false boolean encountered. What's the easiest way to go about this?
if (!headerLogoPresent || !headerMsgDropPresent || !headerMsgDropSubGeneralPresent || !headerUserDropPresent || !headerUserDropSubProfilePresent ||
!headerUserDropSubCredentialsPresent || !headerUserDropSubSettingsPresent || !headerUserDropSubChgPassPresent || !headerUserDropSubRstGridPresent ||
!headerUserDropSubLogOffPresent || !headerSupportDropPresent || !headerSupportDropSubBasePresent || !headerSupportDropSubFaqPresent || !headerSupportDropSubTicketPresent
|| !emailTextInputFieldPresent || !saveButPresent || !bodyTextProfilePresent || !bodyTextEmailPresent || !bodyTextCopyrightPresent)
{
//then throw custom exception for each variable marked false;
}
I have condition, where are no ( ) brackets inside coded by programmer... How can I bracket such ugly coded correctly?
if( c_1 && c_2 || c_3 || c_4 && c_5 || c_6 && c_7 || c_8 || c_9 && c_10)
&& has higher precedence1 in C# than ||. That means your expression is effectively:
if ((c_1 && c_2) || c_3 || (c_4 && c_5) || (c_6 && c_7) || c_8 || (c_9 && c_10))
For further readability, I'd probably extract conditions into local variables with meaningful names. For example:
bool recentlyActive = (c_1 && c_2) || c_3;
bool passwordDisabled = (c_4 && c_5) || (c_6 && c_7);
bool userBanned = c_8 || (c_9 && c_10);
if (recentlyActive || passwordDisabled || userBanned)
{
...
}
1 Precedence in C# is documented in the specification, but it really comes directly out of the grammar. I'm glad of that documentation though, because I wouldn't want to have to read the grammar every time I wanted to understand how operators bind...
I currently have C# code checking for user input as such:
if (e.KeyCode == Keys.Enter && InputTextbox.Text.Contains("good morning")
||
e.KeyCode == Keys.Enter && InputTextbox.Text.Contains("morning"))
Is there another way to use the || "or" statement so that it can all be in the one line? Something like:
if (e.KeyCode == Keys.Enter && InputTextbox.Text.Contains("good morning" || "morning")
You can create an array with the values you want to check and then check if the array contains the TextBox value
string[] a = {"good morning" , "morning");
if (e.KeyCode == Keys.Enter && a.Contains(InputTextbox.Text))
{
}
var allowedText = new List<string> { "good morning", "morning" };
if (e.KeyCode == Keys.Enter && allowedText.Contains(InputTextbox.Text))
{
// do something
}
Hm, for instance: if your InputTextBox is: "Hello good morning" I don't think the above answers will work, if this is what you seek (having a posibly larger string checked against the given smaller strings), you have to check it the other way around:
if (e.KeyCode == Keys.Enter && (InputTextbox.Text.Contains("good morning") || InputTextbox.Text.Contains("morning"))
Just thought I'd point it out, if not the case ignore this answer.
This is sufficient:
if (e.KeyCode == Keys.Enter && InputTextbox.Text.Contains("morning"))
{
}
It is because if InputTextbox.Text.Contains("good morning") is true, InputTextbox.Text.Contains("morning") must be true as well.
I'm sorry to ask such an easy question.. I just need some clarifications, because sometimes I mix the differences up.
Can somebody please help me by explaining the difference between the following if statements?
sending = true;
if (sending && e.AssetType == AssetType.Notecard) //#1
vs.
if ((sending) && (e.AssetType == AssetType.Notecard)) //#2
vs.
if (sending || e.AssetType == AssetType.Notecard) //#3
vs.
if ((sending) || (e.AssetType == AssetType.Notecard)) //#4
In this specific case, I need it to evaluate to something like:
"If(sending == true AND e.AssetType == AssetType.Notecard)"
In an other case I need the if statement to check one string and contents of a list like:
"If(string == "Name" OR List.Contains("string"))
The first and the second statements are the same (parenthesis are not obligatory in this case, because of C# evaluation priorities!)
if (sending && e.AssetType == AssetType.Notecard)
if ((sending) && (e.AssetType == AssetType.Notecard))
just as:
if ((sending == true) && e.AssetType == AssetType.Notecard))
if ((sending) && (e.AssetType == AssetType.Notecard))
Also the 3° and the 4° statement will give the same result, for the same reason mentioned above: http://msdn.microsoft.com/en-us/library/6a71f45d.aspx
I would use these statements:
if (sending && (e.AssetType == AssetType.Notecard))
and:
if ((string == "Name") || List.Contains("string"))
(but please take care of string comparison modes, such as upper/lower cases and cultures:
String.Compare(string, "Name", StringComparison.CurrentCultureIgnoreCase) == 0
compares strings without regard of the case and with the current culture)
There is no any difference in those codes.
if ((sending) && (e.AssetType == AssetType.Notecard)) and if (sending && e.AssetType == AssetType.Notecard) evaluates into the same thing.
if(sending == true) or if(sending) is the same thing too.
If you're asking about difference between || and &&:
|| is a LOGICAL-OR. It's enough that only one condition would be TRUE to pass if
&& is a LOGICAL-AND. All conditions must be TRUE in order to pass if
In both cases the evaluation will be done from the left to right.
Example of sequence:
if ((sending) && (e.AssetType == AssetType.Notecard)) => if sending==true AND ..rest..
For the first and second statements produce the same result and for the third and fourth statements also produce the same result.
A couple of things to clarify:
In this case, parentheses are not required and it is just extra code.
When you use Logical-AND operation, the first part is always evaluated, and the second part will only be evaluated if the first part is true.
When you use Logical-OR operation, both parts are always evaluated.
When you have more than +2 expressions, then use parentheses to clarify your intentions. e.g. if(A && B || C) is the same as if((A && B) || C) because the Operators Precedence. but if you want the logical-OR operation to be execute first, then you must use parentheses to override the precedence if(A && (B || C))
Furthermore, if(A && B == C) is the same as if(A && (B == C)) because Equality operation has higher precedence than logical-AND