将文本格式化为帕斯卡命名法或驼峰命名法的算法

8
2个回答

3
我在http://www.perlmonks.org/?node_id=336331上找到了一个Perl程序员就这个问题争论的帖子。
我希望这不会成为对问题的无解答案,但我认为你会遇到一个问题,那就是这将是一个非常开放式的算法,可能会有很多“失误”和“命中”。例如,假设您输入:
camelCase("hithisisatest");

输出可能是:-
"hiThisIsATest"

或者:

"hitHisIsATest"

算法无法知道应该选择哪一个。你可以添加一些额外的代码来指定更常见的单词,但仍会出现错误(Peter Norvig在http://norvig.com/spell-correct.html编写了一个非常小的拼写纠正器,可能会在算法方面有所帮助,我也编写了一个C#实现,如果您使用C#的话)。

我同意Mark的看法,并认为最好的方法是使用分隔输入的算法,例如this_is_a_test并将其转换。这很容易实现,即:

SetPhraseCase(phrase, CamelOrPascal):
    if no delimiters
     if camelCase
      return lowerFirstLetter(phrase)
     else
      return capitaliseFirstLetter(phrase)
    words = splitOnDelimiter(phrase)
    if camelCase 
      ret = lowerFirstLetter(first word) 
     else
      ret = capitaliseFirstLetter(first word)
    for i in 2 to len(words): ret += capitaliseFirstLetter(words[i])
    return ret

capitaliseFirstLetter(word):
    if len(word) <= 1 return upper(word)
    return upper(word[0]) + word[1..len(word)]

lowerFirstLetter(word):
    if len(word) <= 1 return lower(word)
    return lower(word[0]) + word[1..len(word)]

如果您愿意,您也可以用一个适当的大小写算法来替换我的capitaliseFirstLetter()函数。

上述算法的C#实现如下(带有测试用例的完整控制台程序):

using System;

class Program {
  static void Main(string[] args) {

    var caseAlgorithm = new CaseAlgorithm('_');

    while (true) {
      string input = Console.ReadLine();

      if (string.IsNullOrEmpty(input)) return;

      Console.WriteLine("Input '{0}' in camel case: '{1}', pascal case: '{2}'",
        input,
        caseAlgorithm.SetPhraseCase(input, CaseAlgorithm.CaseMode.CamelCase),
        caseAlgorithm.SetPhraseCase(input, CaseAlgorithm.CaseMode.PascalCase));
    }
  }
}

public class CaseAlgorithm {

  public enum CaseMode { PascalCase, CamelCase }

  private char delimiterChar;

  public CaseAlgorithm(char inDelimiterChar) {
    delimiterChar = inDelimiterChar;
  }

  public string SetPhraseCase(string phrase, CaseMode caseMode) {

    // You might want to do some sanity checks here like making sure
    // there's no invalid characters, etc.

    if (string.IsNullOrEmpty(phrase)) return phrase;

    // .Split() will simply return a string[] of size 1 if no delimiter present so
    // no need to explicitly check this.
    var words = phrase.Split(delimiterChar);

    // Set first word accordingly.
    string ret = setWordCase(words[0], caseMode);

    // If there are other words, set them all to pascal case.
    if (words.Length > 1) {
      for (int i = 1; i < words.Length; ++i)
        ret += setWordCase(words[i], CaseMode.PascalCase);
    }

    return ret;
  }

  private string setWordCase(string word, CaseMode caseMode) {
    switch (caseMode) {
      case CaseMode.CamelCase:
        return lowerFirstLetter(word);
      case CaseMode.PascalCase:
        return capitaliseFirstLetter(word);
      default:
        throw new NotImplementedException(
          string.Format("Case mode '{0}' is not recognised.", caseMode.ToString()));
    }
  }

  private string lowerFirstLetter(string word) {
    return char.ToLower(word[0]) + word.Substring(1);
  }

  private string capitaliseFirstLetter(string word) {
    return char.ToUpper(word[0]) + word.Substring(1);
  }
}

0
唯一的方法就是通过字典逐个运行单词的每个部分。
"mynameisfred"只是一个字符数组,将其拆分为my Name Is Fred意味着理解每个字符的连接含义。
如果输入以某种方式分隔,比如"my name is fred"或"my_name_is_fred",你可以很容易地做到这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接