简体   繁体   中英

C# advanced search in list

I have in-memory List of strings containing two items: 'product 1 max' and 'product 1 min'. How I can search and get 'product 1 min' when user input is 'product min'?

note there are some missing words in middle.

var list = new List<string> {"product 1 max", "product 1 min" };
//user input 'product min' and he expected 'product 1 min'

One way of doing it would be to split the input and match it against each word in the list of strings.

var list = new List<string> { "product 1 max", "product 1 min" };
var input = "product min";
List<string> inputParts = input.Split(' ').ToList();

// contains all the input strings
List<string> results = list.Where(x => x.Split(' ').Intersect(inputParts).Count() == inputParts.Count).ToList();

// partial matching strings
List<string> partialMatches = list.Where(x => x.Split(' ').Intersect(inputParts).Count() > 0).ToList();

Documentation on the Intersect method can be found here

If you split the input into words, you can filter the list to the matches that contain all the input words:

var inputWords = input.Split(' ');
var ans = list.Where(s => inputWords.All(s.Contains)).ToList();

NOTE: s.Contains is a shorter, more efficient (more obscure) way of doing w => s.Contains(w)

A way of achieve that is use the Damerau-Levenshtein algorithm. This an algorithm that basically calculates how many changes would take to one string becomes equals to another, it can be implemented manually but it's kinda tricky and there is already a library ( SoftWx.Match ) that encapsulates the logic for you.

SoftWx.Match has a static method called DamerauOSA(string value1, string value2) that returns a double between 0 and 1 telling how like the two strings are, mixing this with LINQ you can easily.

List<string> products = new List<string>()
{
    "product 1 max",
    "product 1 min"
};
var stringToCompare = "product min";

products.ForEach(x => Console.WriteLine($"Item {x} against {stringToCompare} has {Similarity.DamerauOSA(x, stringToCompare)} points of similarity"));

// 0.80 is an arbitrary number of how much "equality" you want from both strings
var filtered = products.Where(x => Similarity.DamerauOSA(x, stringToCompare) > 0.80).ToList();

Console.WriteLine("Filtered");
filtered.ForEach(x => Console.WriteLine(x));

Working example here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM