/// <summary> /// Get images that are within one "edit" of matching an image in the collection /// </summary> public IEnumerable <string> GetApproximateMatchingImages(IEnumerable <string> searchTerms) { var fullPathsToImages = new List <string>(); foreach (var term in searchTerms) { lock (_padlock) { const int kMaxEditDistance = 1; var itemFormExtractor = new ApproximateMatcher.GetStringDelegate <KeyValuePair <string, List <string> > >(pair => pair.Key); var matches = ApproximateMatcher.FindClosestForms <KeyValuePair <string, List <string> > >(_indexOfWordsToRelativePath, itemFormExtractor, term.ToLowerInvariant(), ApproximateMatcherOptions.None, kMaxEditDistance); if (matches != null && matches.Count > 0) { foreach (var keyValuePair in matches) { fullPathsToImages.AddRange(keyValuePair.Value.Select(GetFullPath)); } } } } var results = new List <string>(); fullPathsToImages.Distinct().ForEach(p => results.Add(p)); return(_fixPaths(results)); }
/// <summary> /// Get an list of languages that match the given string in some way (code, name, country) /// </summary> public IEnumerable <LanguageInfo> SuggestLanguages(string searchString) { if (searchString != null) { searchString = searchString.Trim(); } if (string.IsNullOrEmpty(searchString)) { yield break; } if (searchString == "*") { // there will be duplicate LanguageInfo entries for 2 and 3 letter codes var all_languages = new HashSet <LanguageInfo>(_codeToLanguageIndex.Select(l => l.Value)); foreach (LanguageInfo languageInfo in all_languages.OrderBy(l => l, new ResultComparer(searchString))) { yield return(languageInfo); } } else { IEnumerable <LanguageInfo> matchOnCode = from x in _codeToLanguageIndex where x.Key.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase) select x.Value; List <LanguageInfo>[] matchOnName = (from x in _nameToLanguageIndex where x.Key.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase) select x.Value).ToArray(); List <LanguageInfo>[] matchOnCountry = (from x in _countryToLanguageIndex where x.Key.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase) select x.Value).ToArray(); if (!matchOnName.Any()) { // look for approximate matches const int kMaxEditDistance = 3; var itemFormExtractor = new ApproximateMatcher.GetStringDelegate <KeyValuePair <string, List <LanguageInfo> > >(pair => pair.Key); IList <KeyValuePair <string, List <LanguageInfo> > > matches = ApproximateMatcher.FindClosestForms(_nameToLanguageIndex, itemFormExtractor, searchString, ApproximateMatcherOptions.None, kMaxEditDistance); matchOnName = (from m in matches select m.Value).ToArray(); } var combined = new HashSet <LanguageInfo>(matchOnCode); foreach (List <LanguageInfo> l in matchOnName) { combined.UnionWith(l); } foreach (List <LanguageInfo> l in matchOnCountry) { combined.UnionWith(l); } foreach (LanguageInfo languageInfo in combined.OrderBy(l => l, new ResultComparer(searchString))) { yield return(languageInfo); } } }
/// <summary> /// Get an list of languages that match the given string in some way (code, name, country) /// </summary> public IEnumerable <LanguageInfo> SuggestLanguages(string searchString) { if (searchString != null) { searchString = searchString.Trim().ToLowerInvariant(); } if (string.IsNullOrEmpty(searchString)) { yield break; } else if (searchString == "*") { foreach (var l in from x in CodeToLanguageIndex select x.Value) { yield return(Set3LetterCode(l)); } } else { IEnumerable <LanguageInfo> matchOnCode = from x in CodeToLanguageIndex where x.Key.ToLowerInvariant().StartsWith(searchString) select x.Value; var matchOnName = from x in NameToLanguageIndex where x.Key.ToLowerInvariant().StartsWith(searchString) select x.Value; if (!matchOnName.Any()) { // look for approximate matches const int kMaxEditDistance = 3; var itemFormExtractor = new ApproximateMatcher.GetStringDelegate <KeyValuePair <string, List <LanguageInfo> > >(pair => pair.Key); var matches = ApproximateMatcher.FindClosestForms <KeyValuePair <string, List <LanguageInfo> > >(NameToLanguageIndex, itemFormExtractor, searchString, ApproximateMatcherOptions.None, kMaxEditDistance); matchOnName = from m in matches select m.Value; } List <LanguageInfo> combined = new List <LanguageInfo>(matchOnCode); foreach (var l in matchOnName) { combined.AddRange(l); } List <LanguageInfo> sorted = new List <LanguageInfo>(combined.Distinct()); sorted.Sort(new ResultComparer(searchString)); foreach (var languageInfo in sorted) { yield return(Set3LetterCode(languageInfo)); } } }
private IEnumerable <object> GetMatchingPictures(IEnumerable <string> keywords, out bool foundExactMatches) { var pictures = new List <string>(); foundExactMatches = false; foreach (var term in keywords) { List <string> picturesForThisKey; //first, try for exact matches if (_wordToPartialPathIndex.TryGetValue(term, out picturesForThisKey)) { pictures.AddRange(picturesForThisKey); foundExactMatches = true; } //then look for approximate matches else { foundExactMatches = false; var kMaxEditDistance = 1; var itemFormExtractor = new ApproximateMatcher.GetStringDelegate <KeyValuePair <string, List <string> > >(pair => pair.Key); var matches = ApproximateMatcher.FindClosestForms <KeyValuePair <string, List <string> > >(_wordToPartialPathIndex, itemFormExtractor, term, ApproximateMatcherOptions.None, kMaxEditDistance); if (matches != null && matches.Count > 0) { foreach (var keyValuePair in matches) { pictures.AddRange(keyValuePair.Value); } } } } var results = new List <object>(); pictures.Distinct().ForEach(p => results.Add(p)); return(results); }
private IEnumerable<object> GetMatchingPictures(IEnumerable<string> keywords, out bool foundExactMatches) { var pictures = new List<string>(); foundExactMatches = false; foreach (var term in keywords) { List<string> picturesForThisKey; //first, try for exact matches if (_wordToPartialPathIndex.TryGetValue(term, out picturesForThisKey)) { pictures.AddRange(picturesForThisKey); foundExactMatches = true; } //then look for approximate matches else { foundExactMatches = false; var kMaxEditDistance = 1; var itemFormExtractor = new ApproximateMatcher.GetStringDelegate<KeyValuePair<string, List<string>>>(pair => pair.Key); var matches = ApproximateMatcher.FindClosestForms<KeyValuePair<string, List<string>>>(_wordToPartialPathIndex, itemFormExtractor, term, ApproximateMatcherOptions.None, kMaxEditDistance); if (matches != null && matches.Count > 0) { foreach (var keyValuePair in matches) { pictures.AddRange(keyValuePair.Value); } } } } var results = new List<object>(); pictures.Distinct().ForEach(p => results.Add(p)); return results; }
/// <summary> /// Get an list of languages that match the given string in some way (code, name, country) /// </summary> public IEnumerable <LanguageInfo> SuggestLanguages(string searchString) { if (searchString != null) { searchString = searchString.Trim(); } if (string.IsNullOrEmpty(searchString)) { yield break; } if (searchString == "*") { // there will be duplicate LanguageInfo entries for 2 and 3 letter codes and equivalent tags var all_languages = new HashSet <LanguageInfo>(_codeToLanguageIndex.Select(l => l.Value)); foreach (LanguageInfo languageInfo in all_languages.OrderBy(l => l, new ResultComparer(searchString))) { yield return(languageInfo); } } // if the search string exactly matches a hard-coded way to say "sign", show all the sign languages // there will be duplicate LanguageInfo entries for equivalent tags else if (new [] { "sign", "sign language", "signes", "langage des signes", "señas", "lenguaje de señas" }.Contains(searchString.ToLowerInvariant())) { var parallelSearch = new HashSet <LanguageInfo>(_codeToLanguageIndex.AsParallel().Select(li => li.Value).Where(l => l.Names.AsQueryable().Any(n => n.ToLowerInvariant().Contains("sign")))); foreach (LanguageInfo languageInfo in parallelSearch) { yield return(languageInfo); } } else { IEnumerable <LanguageInfo> matchOnCode = from x in _codeToLanguageIndex where x.Key.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase) select x.Value; List <LanguageInfo>[] matchOnName = (from x in _nameToLanguageIndex where x.Key.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase) select x.Value).ToArray(); // Apostrophes can cause trouble in lookup. Unicode TR-29 inexplicably says to use // u2019 (RIGHT SINGLE QUOTATION MARK) for the English apostrophe when it also defines // u02BC (MODIFIER LETTER APOSTROPHE) as a Letter character. Users are quite likely to // type the ASCII apostrophe (u0027) which is defined as Punctuation. The current // data appears to use u2019 in several language names, which means that users might // end up thinking the language isn't in our database. // See https://silbloom.myjetbrains.com/youtrack/issue/BL-6339. if (!matchOnName.Any() && searchString.Contains('\'')) { searchString = searchString.Replace('\'', '\u2019'); matchOnName = (from x in _nameToLanguageIndex where x.Key.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase) select x.Value).ToArray(); } List <LanguageInfo>[] matchOnCountry = (from x in _countryToLanguageIndex where x.Key.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase) select x.Value).ToArray(); if (!matchOnName.Any()) { // look for approximate matches const int kMaxEditDistance = 3; var itemFormExtractor = new ApproximateMatcher.GetStringDelegate <KeyValuePair <string, List <LanguageInfo> > >(pair => pair.Key); IList <KeyValuePair <string, List <LanguageInfo> > > matches = ApproximateMatcher.FindClosestForms(_nameToLanguageIndex, itemFormExtractor, searchString, ApproximateMatcherOptions.None, kMaxEditDistance); matchOnName = (from m in matches select m.Value).ToArray(); } var combined = new HashSet <LanguageInfo>(matchOnCode); foreach (List <LanguageInfo> l in matchOnName) { combined.UnionWith(l); } foreach (List <LanguageInfo> l in matchOnCountry) { combined.UnionWith(l); } var ordered = combined.OrderBy(l => l, new ResultComparer(searchString)); foreach (LanguageInfo languageInfo in ordered) { yield return(languageInfo); } } }