【问题标题】:CamelCase conversion to friendly name, i.e. Enum constants; Problems?CamelCase 转换为友好名称,即枚举常量;问题?
【发布时间】:2010-09-01 19:28:57
【问题描述】:

在我对this question 的回答中,我提到我们使用UpperCamelCase 解析来获取未使用Description 属性修饰的枚举常量的描述,但它很幼稚,并且并非在所有情况下都有效。我重新审视了它,这就是我想出的:

var result = Regex.Replace(camelCasedString, 
                            @"(?<a>(?<!^)[A-Z][a-z])", @" ${a}");
result = Regex.Replace(result,
                            @"(?<a>[a-z])(?<b>[A-Z0-9])", @"${a} ${b}");

第一个 Replace 查找一个大写字母,后跟一个小写字母,除非大写字母是字符串的开头(以避免必须返回和修剪),并在前面添加一个空格。它处理您的基本 UpperCamelCase 标识符,以及像 FDICInsured 这样的全大写首字母缩略词。

第二个 Replace 查找后跟一个大写字母或数字的小写字母,并在两者之间插入一个空格。这是为了处理特殊但常见的中间或尾随首字母缩略词,或标识符中的数字(前导数字除外,这通常在 C 风格的语言中是被禁止的)。

运行一些基本单元测试,这两者的组合正确分隔了以下所有标识符:NoDescription、HasLotsOfWords、AAANoDescription、ThisHasTheAcronymABCInTheMiddle、MyTrailingAcronymID、TheNumber3、IDo3Things、IAmAValueWithSingleLetterWords 和 Basic(未添加任何空格) .

所以,我发布此内容首先是为了与其他可能觉得它有用的人分享,其次是问两个问题:

  1. 任何人都看到了一个遵循常见的 CamelCase-ish 约定的情况,这种情况不会以这种方式正确地分成友好的字符串?我知道它不会分隔相邻的首字母缩略词 (FDICFCUAInsured),不会对 FdicInsured 等“正确”的驼峰式首字母缩略词进行大写,或者将 lowerCamelCased 标识符的第一个字母大写(但很容易添加 - result = Regex.Replace(result, "^[a-z]", m=&gt;m.ToString().ToUpper());)。还有什么?

  2. 谁能找到一种方法来表达这一说法,或者更优雅?我一直在寻找组合 Replace 调用,但是由于它们对匹配项做了两种不同的事情,因此这两个字符串无法完成。它们可以通过 String 上的 RegexReplace 扩展方法组合成一个方法链,但谁能想到更好的方法?

【问题讨论】:

  • pet-peeve time:“首字母缩略词”是发音像单词的缩写(雷达、北约、正则表达式)。拼写的缩写(ABC、FDIC、XML)实际上称为“首字母缩写词”。

标签: c# regex string


【解决方案1】:

因此,虽然我同意 Hans Passant 的观点,但我不得不说,作为扶手椅正则表达式用户,我必须尝试将其作为一个正则表达式。

(?<a>(?<!^)((?:[A-Z][a-z])|(?:(?<!^[A-Z]+)[A-Z0-9]+(?:(?=[A-Z][a-z])|$))|(?:[0-9]+)))

是我想出的。它似乎通过了您在问题中提出的所有测试。

所以

var result = Regex.Replace(camelCasedString, @"(?<a>(?<!^)((?:[A-Z][a-z])|(?:(?<!^[A-Z]+)[A-Z0-9]+(?:(?=[A-Z][a-z])|$))|(?:[0-9]+)))", @" ${a}");

一次性完成。

【讨论】:

  • 嘿...我知道我迟到了几年,但是如果 camelCasedString 包含这种类型的括号 (),这个正则表达式会插入一个额外的空格。例如,字符串“Hello there (mate)”将被替换为“HELLO THERE (MATE)” 你知道为什么吗? :P
【解决方案2】:

并不是说这直接回答了问题,但为什么不通过使用标准 C# API 并将每个类转换为友好名称来进行测试呢?这需要一些手动验证,但它会给你一个很好的标准名称列表来测试。

【讨论】:

  • 因为我喜欢 TDD 方法。 AFAIK 这将正确解析您可能在代码中看到的任何标识符,并验证了上述特定情况,每个情况都代表一个子集。如果有人想到了一个会破坏它的案例,那么编写一个测试该案例的测试几乎是微不足道的。
  • 我想我有点困惑。如何创建与测试驱动开发正交的大型测试集?
  • @AdamYost,你确实意识到你在评论 4 年前流行的东西,对吧?
【解决方案3】:

假设您遇到的每个案例都适用于此(您向我们询问了一些不适用的示例,然后给了我们一些示例,因此您甚至没有留下任何问题)。

这仍然会将 UI 绑定到编程标识符,从而使编程和 UI 更改都变得脆弱。

它仍然假定您的程序只能以一种语言使用。要么你的潜在市场太小以至于仅仅索引一组名称就足够可扩展(例如,一个客户定制或内部项目),或者你假设你永远不会成功到需要使用其他语言或您首选语言的其他方言。

“好吧,只要我们失败了,它就会起作用”听起来像是平衡设计的及格分数吗?

要么对其进行编码以使用资源,要么对其进行编码以盲目地传递枚举名称或使用名称数组,因为至少以后可以修改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-11
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 2011-10-02
    相关资源
    最近更新 更多