代码之家  ›  专栏  ›  技术社区  ›  mmattax

一种“spacify”camelcased字符串的算法

  •  3
  • mmattax  · 技术社区  · 16 年前

    很基本,我只是好奇其他人如何实现这个算法,想看看是否有任何聪明的技巧来优化算法…我只是为了一个项目,我正在努力实现这个。

    如果有一根骆驼皮箱里的绳子,你会怎么做呢?

    例如给出 福布加尔克 我想要 福格峡谷 回来。

    这是我在c_中的算法:

    
    static void Main(string[] args)
    {
        Console.WriteLine(UnCamelCase("FooBarGork"));
    }
    public static string UnCamelCase(string str)
    {
        StringBuilder sb = new StringBuilder();
        for (int i =  0; i < str.Length; i++)
        {
            if (char.IsUpper(str, i) && i > 0) sb.Append(" ");
            sb.Append(str[i]);
        }
        return sb.ToString();
    }
    
    

    既然你必须访问每个角色一次,我相信最好的情况是o(n)。你将如何实现这一点?

    13 回复  |  直到 6 年前
        1
  •  18
  •   Community kfsone    7 年前

    我已经能感觉到火焰了,但我喜欢这种东西的regex。

    public static string UnCamelCase(string str)
    {
        return Regex.Replace(str, "([a-z])([A-Z])", "$1 $2");
    }
    

    (这可能不会比您的实现速度快,但是 更清楚。)

    显然,这会更快(在运行时)

    private static Regex _unCamelRegex = new Regex("([a-z])([A-Z])", RegexOptions.Compiled);
    
    public static string UnCamelCase(string str)
    {
        return _unCamelRegex.Replace(str, "$1 $2");
    }
    

    这可以解决皮特·柯克汉姆提出的问题 below (至于像httprequest这样的驼峰大小写字符串):

    private static Regex _unCamelRegex1 = new Regex("([a-z])([A-Z])", RegexOptions.Compiled);
    private static Regex _unCamelRegex2 = new Regex("([A-Z]+)([A-Z])([a-z])", RegexOptions.Compiled);
    
    public static string UnCamelCase(string str)
    {
        return _unCamelRegex2.Replace(_unCamelRegex1.Replace(str, "$1 $2"), "$1 $2$3");
    }
    

    这个需要 HTTPRequestFOOBarGork 回报 HTTP Request FOO Bar Gork


    因此,我使用ops实现(使用'start at 1 and skip the>0 check'更改)和我的第二个回复(使用静态编译的regex对象)对正则表达式方法测试了迭代方法。注意,结果不包括regex的编译时间。对于200万个调用(使用相同的foobargork输入):

    迭代: 00∶00:0.80
    Regex: 00∶00:6.71

    很明显,迭代方法是 许多的 更有效率。我已经包含了一个固定版本的ops实现( as suggested 作者jason punyon,任何功劳都应该归于他)这也考虑到了一个空的或空的论点:

    public static string UnCamelCaseIterative(string str)
    {
        if (String.IsNullOrEmpty(str))
            return str;
    
        /* Note that the .ToString() is required, otherwise the char is implicitly
         * converted to an integer and the wrong overloaded ctor is used */
        StringBuilder sb = new StringBuilder(str[0].ToString());
        for (int i = 1; i < str.Length; i++)
        {
            if (char.IsUpper(str, i))
                sb.Append(" ");
            sb.Append(str[i]);
        }
        return sb.ToString();
    }
    
        2
  •  2
  •   Indeed is Trash    16 年前

    为什么不从1开始呢?

    您可以取消&I>0支票…

        3
  •  1
  •   Pete Kirkham    16 年前

    通常,我的去融合方法比较复杂,因为“http request”应该变成“http请求”而不是“http请求”,不同的应用程序处理数字的方式也不同。

        4
  •  1
  •   TJ L    16 年前

    下面是一个php示例

    function spacify($str) {
      return preg_replace('/([a-z])([A-Z])/', "\1 \2", $str);
    }
    
        5
  •  0
  •   Noldorin    16 年前

    看着你的代码,它似乎被弄坏了(当你把它复制过来的时候)。除了修复for循环外,我假设您只是缺少一个if语句,该语句在 sb.Append(" ") 钻头。否则当然没问题。对于一个泛型字符串,你不会得到比o(n)更好的结果。

    现在显然有一个单行的regex replace调用来完成这个任务,但实际上没有理由为这样一个简单的任务做这样的事情。为了便于阅读,最好尽量避免使用regex。

        6
  •  0
  •   Ian Jacobs    16 年前

    我可能会用类似的方法来做,只是可能会用一个stringbuilder来代替:

    str=str.replace(str[i], " "+str[i]);
    

    不过,我敢肯定你的方法最终会更有效率。

        7
  •  0
  •   Stoo    16 年前

    我会和…

    public static string UnCamelCase(string str) {
        Regex reg = new Regex("([A-Z])");
    
        return reg.Replace(str, " $1").Trim();
    }
        8
  •  0
  •   Tomalak    16 年前

    一些正则表达式类型知道“\u”(大写)和“\u”(小写)字符类。他们可以取代这个:

    (?<=\U)(?=\u)
    

    有一个空间。对于那些你可能不知道这些课程的人,这可以做到:

    (?<=[a-z])(?=[A-Z])   // replace with a single space again
    

    说明:正则表达式匹配小写和大写字符之间的点。camelcasedwords是通常发生这种情况的唯一结构。

    CamelCasedWord
        ^^   ^^           // match occurs between the ^
    
        9
  •  0
  •   PEZ    16 年前

    像这样的东西(巨蟒)?

    >>> s = 'FooBarGork'
    >>> s[0] + re.sub(r'([A-Z])', r' \1', s[1:])
    'Foo Bar Gork'
    
        10
  •  0
  •   Ian G    16 年前

    不是很刺激,但是:

        public static string UnCamelCase(string str)
        {
            StringBuilder sb = new StringBuilder();
    
            foreach (char c in str.ToCharArray())
            {
                if (System.Convert.ToInt32(c) <= 90) sb.Append(" ");
                sb.Append(c);
            }
            return sb.ToString().Trim();
        }
    
    
            //Console.WriteLine(System.Convert.ToInt32('a')); // 97
            //Console.WriteLine(System.Convert.ToInt32('z')); // 122
            //Console.WriteLine(System.Convert.ToInt32('A')); // 65
            //Console.WriteLine(System.Convert.ToInt32('Z')); // 90
    
        11
  •  0
  •   TJ L    16 年前

    以下是mootools javascript库的工作原理(尽管它们是“连字符的”,但是很容易将连字符替换为空格。

    /*
    Property: hyphenate
        Converts a camelCased string to a hyphen-ated string.
    
    Example:
        >"ILikeCookies".hyphenate(); //"I-like-cookies"
    */
    
    hyphenate: function(){
        return this.replace(/\w[A-Z]/g, function(match){
            return (match.charAt(0) + '-' + match.charAt(1).toLowerCase());
        });
    },
    
        12
  •  0
  •   user unknown    13 年前
    echo "FooBarGork" | sed -r 's/([A-Z])/ \1/g;s/^ //'
    
        13
  •  0
  •   Yitzhak Weinberg    6 年前

    获取大写的索引

    短句法

    Regex.Match("hello,World!", @"(\p{Lu})").Index
    

    结果6

    长例

    使用System.Text.RegularExpressions;

    namespace namespace.Helpers
    {
        public static class Helper
        {
            public static int IndexOfUppercase(this string str, int startIndex = 0)
            {
                return str.IndexOfRegex(@"(\p{Lu})", startIndex);
            }
    
            public static int IndexOfRegex(this string str, string regex, int startIndex )
            {
                return str.Substring(startIndex).IndexOfRegex(regex);
            }
    
            public static int IndexOfRegex(this string str, string regex)
            {
                var match = Regex.Match(str, regex);
                if (match.Success)
                {
                    return match.Index;
                }
                return -1;
            }
        }
    }