Это на самом деле не проблема специально для решения с Razor. Я думаю, что лучший способ сделать это было бы иметь специальный метод. Простые расщепления не будут делать то, что вы хотите, потому что вы не знаете логической точки, в которой нужно расщепляться, и я не могу придумать и простого решения Regex для него. Итак, вот очень простой пример, который перемещается через строку символ за символом, чтобы идентифицировать основные границы слова:
public static IEnumerable<string> SplitString(string value)
{
char last = char.MinValue;
bool inWord = false;
string word = string.Empty;
foreach (char c in s)
{
if (char.IsLetter(c))
{
// Covers situations with apostrophised characters, e.g. 's
if (last == '\'' && char.IsLetter(c) && inWord)
{
word += last;
word += c;
yield return word;
word = string.Empty;
inWord = false;
}
else if (char.IsUpper(c) && !inWord)
{
// Start of a new word.
word += c;
inWord = true;
}
else if (char.IsUpper(c))
{
// Return the last word.
yield return word;
// Start a new string.
word = string.Empty + c;
inWord = true;
}
else
{
// Append to the current string.
word += c;
}
}
else
{
if (c == '\'' && inWord)
{
// If we are at an apostrophe, set and then skip
last = c;
continue;
}
if (word.Length > 0)
{
// Otherwise, if we have a previous word, return.
yield return word;
// Clear ready for the next word.
word = string.Empty;
inWord = false;
}
}
last = c;
}
// If there is one more remaining word, return it.
if (word.Length > 0)
yield return word;
}
К которым вы можете присоединиться / объединить, используя
string result = string.Join(", ", SplitString(sentence));
Этот метод использует способность компилятора создавать конечный автомат, когда мы используем yield
. Это хорошо, потому что мы можем перечислять через поток символов и возвращать результаты, когда мы действительно их получаем.
Теперь, это не будет работать напрямую в шаблоне Razor, так как вам нужно объявить метод шаблона. Грязный способ сделать это - объявить функцию, используя экземпляр Func<string, IEnumerable<string>>
:
@{
Func<string, IEnumerable<string>> splitter = s =>
{
char last = char.MinValue;
bool inWord = false;
string word = string.Empty;
IList<string> words = new List<string>();
foreach (char c in s)
{
if (char.IsLetter(c))
{
if (last == '\'' && char.IsLetter(c) && inWord)
{
word += last;
word += c;
words.Add(word);
word = string.Empty;
inWord = false;
}
else if (char.IsUpper(c) && !inWord)
{
word += c;
inWord = true;
}
else if (char.IsUpper(c))
{
words.Add(word);
word = string.Empty + c;
inWord = true;
}
else
{
word += c;
}
}
else
{
if (c == '\'' && inWord)
{
last = c;
continue;
}
if (word.Length > 0)
{
words.Add(word);
word = string.Empty;
inWord = false;
}
}
last = c;
}
if (word.Length > 0)
words.Add(word);
return words;
};
}
Но даже это не красиво. Это не пуленепробиваемый способ правильного расщепления строки.