将文本格式化为Pascal或者骆驼套的算法
时间:2020-03-05 18:44:22 来源:igfitidea点击:
以这个问题为基础,有一个逻辑或者编码示例,可以将某些文本更改为Pascal或者Camel大小写。
例如:
mynameisfred
变成
Camel: myNameIsFred Pascal: MyNameIsFred
解决方案
回答
唯一的方法是通过词典运行单词的每个部分。
" mynameisfred"只是一个字符数组,将其拆分为"我的名字,我的名字是Fred"意味着理解每个字符的连接含义。
如果输入以某种方式分开,例如"我的名字叫弗雷德"或者" my_name_is_fred"。
回答
我在http://www.perlmonks.org/?node_id=336331上找到了一群Perl家伙争论这个问题的话题。
我希望这不是解决问题的答案,但我会说我们有一个问题,因为这将是一个非常开放的算法,可能还会有很多"遗漏"作为命中。例如,假设我们输入了:
camelCase("hithisisatest");
输出可能是:-
"hiThisIsATest"
或者:-
"hitHisIsATest"
该算法无法知道该选择哪种方法。我们可以添加一些额外的代码来指定我们希望使用更常见的单词,但是还是会出现遗漏现象(Peter Norvig在http://norvig.com/spell-correct.html上写了一个很小的拼写校正器,这可能有助于算法-wise,如果C#是语言,我写了一个Cimplementation。
我同意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()函数。
上述算法的实现如下(带有测试工具的完整控制台程序):
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); } }