2011-11-24 62 views
1

我相对(更像是完全)新的剃须刀世界,并不可避免地打我的第一个障碍。我是一名也是CMS Umbraco新手的Web开发人员,因此我一直在使用剃须刀进行脚本编写。如何使用剃刀分割文本字符串(在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 
    } 
} 

回答

2

这不是专门解决剃刀问题的问题。我认为这样做的最好方法是有一个专门的方法。简单的分割不会做你想要的,因为你不知道分割的逻辑点,我也想不出一个简单的Regex解决方案。所以在这里是通过串字符为单位移动,以确定基本的单词边界一个非常简单的例子:使用

string result = string.Join(", ", SplitString(sentence)); 

该方法利用的编译器的能力

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; 
} 

,您可以加入/ concatentate当我们使用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; 
    }; 
    } 

但即使是不漂亮。这不是一种正确分割字符串的防弹方法。

+0

哇,谢谢你的回答,马修!只看代码告诉我,我绝对不会超出我的深度! – mmmoustache

+0

+1细节。 – amelvin