Сделайте любой из Вас знает о легком / очевидном способе для нахождения подстроки в строке при игнорировании некоторых указанных символов для нахождения его. Я думаю, что пример объяснил бы вещи лучше:
Используя Regex не требование для меня, но я добавил тег, потому что это чувствует себя связанным.
Обновление:
Сделать требование более ясным: Мне нужна получающаяся подстрока с проигнорированными символами, не только признак, что данная подстрока существует.
Обновление 2: Некоторые из Вас читают слишком много в пример, извините, я дам другой сценарий, который должен работать:
И в качестве награды (не требуемый по сути), будет замечательно, если будет также не безопасно предположить, что подстрока для нахождения не будет иметь проигнорированных символов на нем, например: учитывая последний пример мы должны смочь сделать:
Извините, если я не был ясен прежде, или тем не менее я не :).
Обновление 3:
Благодаря всем, кто помог!, это - реализация, с которой я работаю на данный момент:
Вот некоторые тесты:
Я использую некоторые пользовательские дополнительные методы, которые я не включаю, но я полагаю, что они должны быть self-explainatory (я добавлю их, если Вам нравится), я взял много Ваших идей для реализации и тестов, но я даю ответ на @PierrOz, потому что он был одной из первых и указал на меня в правильном направлении. Не стесняйтесь продолжать давать предложения как альтернативные решения, или комментирует текущее состояние impl., если Вам нравится.
в вашем примере вы бы сделали:
string input = "Hello, -this-, is a string";
string ignore = "[-,]*";
Regex r = new Regex(string.Format("H{0}e{0}l{0}l{0}o{0} {0}t{0}h{0}i{0}s{0}", ignore));
Match m = r.Match(input);
return m.Success ? m.Value : string.Empty;
Динамически вы построили бы часть [-,] со всеми символами, которые нужно игнорировать, и вы бы вставили эту часть между всеми символами вашего запроса.
Позаботьтесь о '-' в классе []: поместите его в начало или в конец
Таким образом, в более общем смысле это даст что-то вроде:
public string Test(string query, string input, char[] ignorelist)
{
string ignorePattern = "[";
for (int i=0; i<ignoreList.Length; i++)
{
if (ignoreList[i] == '-')
{
ignorePattern.Insert(1, "-");
}
else
{
ignorePattern += ignoreList[i];
}
}
ignorePattern += "]*";
for (int i = 0; i < query.Length; i++)
{
pattern += query[0] + ignorepattern;
}
Regex r = new Regex(pattern);
Match m = r.Match(input);
return m.IsSuccess ? m.Value : string.Empty;
}
Вы можете сделать это с помощью одного Regex, но это будет довольно утомительно. так как после каждого символа вам нужно будет проверить ноль или более игнорируемых символов. Вероятно, проще удалить все игнорируемые символы с помощью Regex.Replace (subject, "[-,]", "");
, а затем проверить, есть ли там подстрока.
Или единственный способ регулярного выражения
Regex.IsMatch(subject, "H[-,]*e[-,]*l[-,]*l[-,]*o[-,]* [-,]*t[-,]*h[-,]*i[-,]*s[-,]*")
Вы можете сделать что-то вроде этого, поскольку большинство из этих ответов требует перестройки строки в той или иной форме.
строка1 - это ваша строка, которую вы хотите просмотреть
//Create a List(Of string) that contains the ignored characters'
List<string> ignoredCharacters = new List<string>();
//Add all of the characters you wish to ignore in the method you choose
//Use a function here to get a return
public bool subStringExist(List<string> ignoredCharacters, string myString, string toMatch)
{
//Copy Your string to a temp
string tempString = myString;
bool match = false;
//Replace Everything that you don't want
foreach (string item in ignoredCharacters)
{
tempString = tempString.Replace(item, "");
}
//Check if your substring exist
if (tempString.Contains(toMatch))
{
match = true;
}
return match;
}
Этот код будет делать то, что вы хотите, хотя я предлагаю вам изменить его в соответствии с вашими потребностями:
string resultString = null;
try
{
resultString = Regex.Match(subjectString, "Hello[, -]*this", RegexOptions.IgnoreCase).Value;
}
catch (ArgumentException ex)
{
// Syntax error in the regular expression
}
Вы всегда можете использовать комбинацию RegEx и поиска по строке
public class RegExpression {
public static void Example(string input, string ignore, string find)
{
string output = string.Format("Input: {1}{0}Ignore: {2}{0}Find: {3}{0}{0}", Environment.NewLine, input, ignore, find);
if (SanitizeText(input, ignore).ToString().Contains(SanitizeText(find, ignore)))
Console.WriteLine(output + "was matched");
else
Console.WriteLine(output + "was NOT matched");
Console.WriteLine();
}
public static string SanitizeText(string input, string ignore)
{
Regex reg = new Regex("[^" + ignore + "]");
StringBuilder newInput = new StringBuilder();
foreach (Match m in reg.Matches(input))
{
newInput.Append(m.Value);
}
return newInput.ToString();
}
}
Использование будет как
RegExpression.Example("Hello, -this- is a string", "-,", "Hello this"); //Should match
RegExpression.Example("Hello, -this- is a string", "-,", "Hello this2"); //Should not match
RegExpression.Example("?A&3/3/C)412&", "&/3C\\)", "A41"); // Should match
RegExpression.Example("?A&3/3/C) 412&", "&/3C\\)", "A41"); // Should not match
RegExpression.Example("?A&3/3/C)412&", "&/3C\\)", "A3C412&"); // Should match
Выход
Вход: Здравствуйте, -this- это строка Игнорировать: -, Найти: Здравствуйте, это
было найдено
Ввод: Здравствуйте, -this - это строка Игнорировать: -, Найти: Здравствуйте, this2
НЕ соответствует
Ввод:? A & 3/3 / C) 412 & Игнорировать: & / 3C) Найти: A41
совпало
Ввод:? A & 3/3 / C) 412 & Игнорировать: & / 3C) Найти: A41
НЕ было найдено
Ввод:? A & 3/3 / C) 412 & Игнорировать: & / 3C) Найти: A3C412 и
совпали
Вот способ сделать это без регулярного выражения с помощью синтаксического анализа строк.
private string GetSubstring()
{
string searchString = "Hello, -this- is a string";
string searchStringWithoutUnwantedChars = searchString.Replace(",", "").Replace("-", "");
string desiredString = string.Empty;
if(searchStringWithoutUnwantedChars.Contains("Hello this"))
desiredString = searchString.Substring(searchString.IndexOf("Hello"), searchString.IndexOf("this") + 4);
return desiredString;
}
РЕДАКТИРОВАТЬ: вот обновленное решение, учитывающее моменты в вашем недавнем обновлении. Идея та же, за исключением того, что если у вас есть одна подстрока, вам нужно будет вставить шаблон игнорирования между каждым символом. Если подстрока содержит пробелы, она будет разделена на пробелы и вставит шаблон игнорирования между этими словами. Если у вас нет необходимости в последней функции (что больше соответствовало вашему исходному вопросу), вы можете удалить Split
и if
проверки, которые обеспечивают этот шаблон.
Обратите внимание, что этот подход не будет самым эффективным.
string input = @"foo ?A&3/3/C)412& bar A341C2";
string substring = "A41";
string[] ignoredChars = { "&", "/", "3", "C", ")" };
// builds up the ignored pattern and ensures a dash char is placed at the end to avoid unintended ranges
string ignoredPattern = String.Concat("[",
String.Join("", ignoredChars.Where(c => c != "-")
.Select(c => Regex.Escape(c)).ToArray()),
(ignoredChars.Contains("-") ? "-" : ""),
"]*?");
string[] substrings = substring.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string pattern = "";
if (substrings.Length > 1)
{
pattern = String.Join(ignoredPattern, substrings);
}
else
{
pattern = String.Join(ignoredPattern, substring.Select(c => c.ToString()).ToArray());
}
foreach (Match match in Regex.Matches(input, pattern))
{
Console.WriteLine("Index: {0} -- Match: {1}", match.Index, match.Value);
}
string input = "Hello, -this- is a string";
string[] searchStrings = { "Hello", "this" };
string pattern = String.Join(@"\W+", searchStrings);
foreach (Match match in Regex.Matches(input, pattern))
{
Console.WriteLine(match.Value);
}
\ W +
будет соответствовать любому не буквенно-цифровому символу. Если вы хотите указать их самостоятельно, вы можете заменить его классом символов, которые следует игнорировать, например [, .-] +
(всегда помещайте символ тире в начале или в конце, чтобы избежать непреднамеренного технические характеристики диапазона). Кроме того, если вам нужно игнорировать регистр, используйте RegexOptions.IgnoreCase
:
Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
Если ваша подстрока имеет форму полной строки, например «Hello this», вы можете легко получить ее в массив сформируйте для searchString
следующим образом:
string[] searchString = substring.Split(new[] { ' ' },
StringSplitOptions.RemoveEmptyEntries);
Вот вариант расширения строки без регекса:
public static class StringExtensions
{
public static bool SubstringSearch(this string s, string value, char[] ignoreChars, out string result)
{
if (String.IsNullOrEmpty(value))
throw new ArgumentException("Search value cannot be null or empty.", "value");
bool found = false;
int matches = 0;
int startIndex = -1;
int length = 0;
for (int i = 0; i < s.Length && !found; i++)
{
if (startIndex == -1)
{
if (s[i] == value[0])
{
startIndex = i;
++matches;
++length;
}
}
else
{
if (s[i] == value[matches])
{
++matches;
++length;
}
else if (ignoreChars != null && ignoreChars.Contains(s[i]))
{
++length;
}
else
{
startIndex = -1;
matches = 0;
length = 0;
}
}
found = (matches == value.Length);
}
if (found)
{
result = s.Substring(startIndex, length);
}
else
{
result = null;
}
return found;
}
}