How to match every word in a regex search? - c#

I'm using regex to search for data in my SQL database.
I have columns Name, Surname, Email, IdNumber
The idea is the user should be able to search for any value from these columns OR a combination of name and surname, but I can't work out how to split the "Walter White" search string so that it'll match Name == "Walter" AND Surname == "White".
Here's my code so far:
var pattern = #$"({search})";
var results = new List<Member>();
foreach (var member in context.Members.Where(x => x.IsActive))
{
// If the currently evaluated item is already in the results, skip.
if (results.Any(x => x.Id == member.Id)) continue;
if (!string.IsNullOrEmpty(member.Name) && Regex.IsMatch(member.Name, pattern, RegexOptions.IgnoreCase))
{
results.Add(member);
continue; // Don't match on any other condition.
}
if (!string.IsNullOrEmpty(member.Surname) && Regex.IsMatch(member.Surname, pattern, RegexOptions.IgnoreCase))
{
results.Add(member);
continue; // Don't match on any other condition.
}
// etc...
}
It works if the search query is the email address, id number, name OR surname, but it fails to match if the search query is the name AND surname.
How can I get it to match on name OR surname?

Related

How can I Using LinQ search in a list by the input and print those that contain the letters?

Hi Im new to Linq and been trying to do this query but wont work, I have problems with the printing of the names, for example it does ask me the letters (inicials) I want, but when it comes to showing the matches they dont print
Here is the query:
string input;
Console.Write("Which fist 2 letters you want to look for? \n");
input = Console.ReadLine();
var search= from s in names
where s == input
orderby s descending
select s;
foreach (var name in search)
{
Console.Write("\t" + name);
}
Here is my list:
string[] names= { "ANE", "CARL", "ANNA", "SOFIE", "ANNIE", "MARIE", "CAMILA", "SCOTT", "STILES", "JESSICA" };
The program does ask for the input but won't print anything as if there are no matches even when there are. How can I make results show up?
example of output
Are you looking for a StartsWith?
var search = names
.Where(name => name.StartsWith(input))
.OrderBy(name => name);

How to Filter data based on two property in linq

I have a list that contain some data like this:
Name | LName
------------
John| Snow
Raymond | Redington
....
I can search in each column with the following code
list.ShapeView().Where(p =>
(p.Name.IndexOf(autoBox.Text, StringComparison.OrdinalIgnoreCase) != -1) ||
(p.LName.IndexOf(autoBox.Text, StringComparison.OrdinalIgnoreCase) != -1)).Apply();
If I type the following text, the results will be filtered correctly
John
Snow
But if I type both of them together
John Snow
no result will be displayed, how can I implement this?
It's not 100% clear what you want to support. If you also want that only part of the TextBox.Text must be contained in either Name or LName, then this should work:
var query = list.ShapeView()
.Where(p => autoBox.Text.IndexOf(p.Name, StringComparison.OrdinalIgnoreCase) != -1
|| autoBox.Text.IndexOf(p.LName, StringComparison.OrdinalIgnoreCase) != -1
|| p.Name.IndexOf(autoBox.Text, StringComparison.OrdinalIgnoreCase) != -1
|| p.LName.IndexOf(autoBox.Text, StringComparison.OrdinalIgnoreCase) != -1);
You could also split on spaces and search the first token in name and the second in lname. But this is also broken, what if someone types "John Lee Hooker"? What is the first name and what is the last name? So you should have two Textboxes.
You can aplly Split to text and use the function Contains
Example:
string[] valores = autoBox.Text.ToUpper().Split(' ');
var query = list.ShapeView()
.Where(p =>valores.Contains(p.Name.ToUpper())||valores.Contains(p.LName.ToUpper()));

find the longest match of a string in list c#

I have a list of string I need to find the longest match of my search string in the list.
for example the list contains : "test", "abc", "testing", "testingap" and my search string is 'testingapplication'
the result should be 'testingap'
here is what I did so far , it does the work but I'm looking is there any better efficient way to do this
string search= "testingapplication";
List<string> names = new List<string>(new[] { "test", "abc", "testing", "testingap" });
List<string> matchedItems = new List<string>();
foreach (string item in names)
{
if (search.Contains(item))
{
matchedItems.Add(item);
Console.WriteLine(item);
}
}
var WordMatch= matchedItems.Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur);
Console.WriteLine("WordMatch"+WordMatch);
Since you are already using LINQ, you could consider ordering your "names" by length via the OrderByDescending() method and grab the first that contains your string using FirstOrDefault() as seen below:
var match = names.OrderByDescending(n => n.Length)
.FirstOrDefault(n => search.Contains(n));
if (match == null)
{
// No match was found, handle accordingly.
}
else
{
// match will contain your longest string
}

Single field extraction from a database using lambda

My problem is connected to the extraction method called lambda ( I am using it in C# ). I have a database and in it I have a table called Students and I wonder if I would be able to extract the firstName and lastName of certain student whose ID matches my search.
I have tried a few things so far without any luck.
A bit of code from my last attempt :
var studentName =
context.Student //context is the variable with the entities and Student is the table
.Where(student => student.StudentID == SomeInt) // extract only the one with the chosen ID
.Select(student => student.FirstName) // tryng only to select the wanted field(s)
.ToString() // since I want it to be displayed in a textbox
Currently you're calling Select on an IQueryable<string> - your query represents a sequence of student first names, even if it only matches a single one.
If you only want a single name, you can use:
var studentName =
context.Student
.Where(student => student.StudentID == SomeInt)
.Select(student => student.FirstName)
.FirstOrDefault();
Then assuming FirstName is a string, you don't need ToString() at all. The value will be null if there's no student with that ID. Alternatively, you could use Single(), SingleOrDefault(), First(), Last() or LastOrDefault(). So for example, you'd then use:
if (studentName == null)
{
// No match found. Return an error or whatever.
}
else
{
// Use studentName
}
(You should only use FirstOrDefault() if you then check for nullity, or pass it on to something else that does so. Otherwise you can end up with a NullReferenceException later which is hard to diagnose.)
If you want both the first and last names, you need to change your projection. For example:
var studentName =
context.Student
.Where(student => student.StudentID == SomeInt)
.Select(student => new { student.FirstName, student.LastName })
.FirstOrDefault();
Now the type of studentName will be an anonymous type - again, it'll be null if there are no matches, but otherwise it will have appropriate FirstName and LastName properties.
You can write something like:
var name = context.Students.FirstOrDefault(c=>c.Id == SomeId).FirstName;
You could try something like this:
var student = context.Student
.Where(student => student.StudentID == studentId)
.Select(student => new
{
FirstName = student.FirstName,
LastName = student.LastName
}).FirstOrDefault();
If any student with studentId exists at all, then you get her first name and her last name, like below:
var firstName = student.FirstName;
var lastName = student.LastName;
If there isn't any student with the given studentId, the result of the above query, would be null. Hence, before you use the dot notation, please validate that the user you are looking for has been found like below:
if(student!=null)
{
// Here you can access both the LastName and
// the FirstName of the found student.
}

LINQ get the best match from the list comparing strings

I have code where I try to find QProduct by productName in a List<QProduct> (lqp) usinq LINQ. The variable productNameInaccurate I get from file name and often contains some other text usually at the end of the string. So for example the productName = '0/2' and the productNameInaccurate that I get from fileName is '0/2 new' etc.
I have this code:
//Get inaccurate product name from filename
productNameInaccurate = fileName.Substring(ind + 1, ind2 - ind - 1).Replace("-", "/");
//Get filtered list of products
List<QProduct> filtered = lqp.Where(x=>productNameInaccurate.StartsWith(x.Name, StringComparison.InvariantCultureIgnoreCase)).ToList();
//Some more filtering - here I need to get best match by productName
if (isDop)
qProduct = filtered.Where(x => x.normy.StartsWith("ČSN EN")).FirstOrDefault();
else
qProduct = filtered.Where(x => !x.normy.StartsWith("ČSN EN")).FirstOrDefault();
It works ok, but I have also productName = '32/63' and productName = '32/63 B I'. This code finds QProduct that has productName == '32/63' even if productNameInaccurate == '32/63 BI'.
What I need is to find best match from the list of QProduct, so that for productNameInaccurate='0/2 new' I get QProduct.Name = '0/2' and for productNameInaccurate='32/63 Bi' I get QProduct.Name = '32/63 B II' instead of QProduct.Name = '32/63'. Ideally get the filtered list sorted by count of matching characters.
"Ideally get the filtered list sorted by count of matching characters."
// Get the filtered list and sort by count of matching characters
IEnumerable<QProduct> filtered = lqp
.Where(x=>productNameInaccurate.StartsWith(x.Name, StringComparison.InvariantCultureIgnoreCase))
.OrderByDesc(x => Fitness(x.ProductName, productNameInaccurate));
static int Fitness(string individual, string target) {
return Enumerable.Range(0, Math.Min(individual.Length, target.Length))
.Count(i => individual[i] == target[i]);
}

Categories