Алгоритм "spacify" строк CamelCased - PullRequest
3 голосов
/ 27 января 2009

Довольно просто, мне просто любопытно, как другие могут реализовать этот алгоритм, и хотел бы посмотреть, есть ли какие-нибудь хитрые приемы для оптимизации алгоритма ... Мне просто нужно было реализовать это для проекта, над которым я работаю.

Учитывая строку в CamelCase, как бы вы ее "spacification"?

например. учитывая FooBarGork Я хочу Foo Bar Gork назад.

Вот мой алгоритм в 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 ]

18 голосов
/ 27 января 2009

Я уже чувствую пламя, но мне нравятся регулярные выражения для такого рода вещей.

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

(Это может быть не быстрее, чем ваша реализация, но для me это более понятно.)

И, очевидно, это было бы еще быстрее (во время выполнения)

private static Regex _unCamelRegex = new Regex("([a-z])([A-Z])", RegexOptions.Compiled);

public static string UnCamelCase(string str)
{
    return _unCamelRegex.Replace(str, "$1 $2");
}

Это решит проблему, поднятую Питом Киркхэмом ниже (что касается строк в верблюжьей оболочке, таких как 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


Таким образом, я протестировал итерационный метод в сравнении с методом регулярных выражений, используя реализацию OP (с изменением 'start at 1 и skip> 0 check') и мой второй ответ (тот, который был статически скомпилирован с объектом Regex). Обратите внимание, что результаты не включают время компиляции регулярных выражений. Для 2 миллионов вызовов (используя один и тот же вход FooBarGork):

Итерация: 00: 00: 00.80
Регулярное выражение: 00: 00: 06.71

Итак, очевидно, что итерационный подход намного эффективнее . Я включил фиксированную версию реализации OP (, как предложено Джейсоном Пуньоном, любой кредит должен идти к нему), которая также учитывает нулевой или пустой аргумент:

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 голосов
/ 27 января 2009

Почему бы не начать с 1?

Вы можете убрать проверку && i> 0 ...

1 голос
/ 27 января 2009

А вот пример PHP

function spacify($str) {
  return preg_replace('/([a-z])([A-Z])/', "\1 \2", $str);
}
1 голос
/ 27 января 2009

Обычно мои методы декамелизации немного сложнее, поскольку «HTTPRequest» должен стать «HTTP-запросом», а не «H T T P-запросом», и разные приложения также обрабатывают цифры по-разному.

0 голосов
/ 05 июля 2018

Получить индекс верхнего регистра

короткий синтаксис

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;
        }
    }
}
0 голосов
/ 09 августа 2011
echo "FooBarGork" | sed -r 's/([A-Z])/ \1/g;s/^ //'
0 голосов
/ 27 января 2009

Вот как это делает библиотека javascript mootools (хотя они «переносят», довольно легко поменять дефис на пробел.

/*
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());
    });
},
0 голосов
/ 27 января 2009

Не очень интересно, но:

    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
0 голосов
/ 27 января 2009

Что-то вроде этого (Python)?

>>> s = 'FooBarGork'
>>> s[0] + re.sub(r'([A-Z])', r' \1', s[1:])
'Foo Bar Gork'
0 голосов
/ 27 января 2009

Некоторые разновидности регулярных выражений знают классы символов "\ u" (верхний регистр) и "\ U" (нижний регистр). Они могут заменить это:

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

с пробелом. Для тех, кто может не знать эти классы, это подойдет:

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

Объяснение: регулярное выражение сопоставляет точку между строчными и заглавными буквами. CamelCasedWords - единственные конструкции, где это обычно происходит.

CamelCasedWord
    ^^   ^^           // match occurs between the ^
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...