Как я могу разделить текстовую строку, используя бритву (в Умбрако)? - PullRequest
1 голос
/ 24 ноября 2011

Я относительно (скорее как полностью) новичок в мире бритв, и неизбежно столкнулся с моим первым препятствием. Я веб-разработчик, который также является новичком в CMS Umbraco, и поэтому я работаю с бритвой для сценариев.

Моя проблема довольно простая, я считаю; Как разделить текстовую строку для отображения 4 разных слов / значений с запятыми между ними?

В идеале я хотел бы включить что-то вроде:

«WhyWontThisWork» в «Почему, не то, что, работа» и, возможно, усложнять вещи: «Почему», не то, что, работа »(со словами вокруг первого слова)

Я пытался использовать этот метод из другого потока, но безрезультатно:

@foreach (string s in "1,2,3".Split(',')) {
  @: s is equal to @s<br/>
}

Попытка реализовать этот синтаксис в моем собственном сценарии выглядит следующим образом и поэтому не работает:

@inherits umbraco.MacroEngines.DynamicNodeContext
@{
    foreach (var x in Model.uctextstring.Split(',')) {
        @x.InnerText
    }
}

1 Ответ

2 голосов
/ 24 ноября 2011

Это на самом деле не проблема специально для решения с 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;
    };
  }

Но даже это не красиво. Это не пуленепробиваемый способ правильного расщепления строки.

...