Добавьте пробелы в Camelcase с заглавными буквами - PullRequest
0 голосов
/ 31 мая 2019

У меня есть внешнее приложение, передающее строки в Camelcase. Пользователи хотят сообщить о строке и хотят отформатировать ее как предложение. Строка может содержать слова со всеми заглавными буквами, которые нужно добавить вокруг.

здесь построена функция, основанная на этом вопросе: Существует ли какая-либо встроенная функция SQL Server для преобразования строки в случае верблюда? однако, это не работает со всеми заглавными буквами. Ниже моя модифицированная версия.


DECLARE @String    NVARCHAR(MAX) = 'ThisIsASentenceWithCAPTIInIt'
    --, @Len       INT         --  = LEN(@String)
      , @Delimiter CHAR(1)       = ' '
      , @Iterator  INT           = 2; --Don't put space to left of first even if it's a capital

WHILE @Iterator <= LEN(@String)
-- Iterate through string
    BEGIN
        -- Check if current character is Uppercase (lowercase = 0)
        IF PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator, 1) COLLATE Latin1_General_CS_AI) <> 0
        -- Do this if capital
            BEGIN
                -- check if the previous character is lowercase, if it is then add a space before the current character.
                IF(
                   (PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator - 1, 1) COLLATE Latin1_General_CS_AI) = 0
                    AND SUBSTRING(@String, @Iterator - 1, 1) <> ' '
                   )
                   OR PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator + 1, 1) COLLATE Latin1_General_CS_AI) = 0)
                    BEGIN
                        SET @String = STUFF(@String, @Iterator, 0, @Delimiter);
                        SET @Iterator+=1;
                END;
                -- check if the next character is lowercase, if it is then add a space before the current character.
                SET @Iterator+=1;
        END;
        ---- Don't care about current character being lowercase. Just continue iterating
        SET @Iterator+=1;
    END;

SELECT @String;

Пример того, что я получаю из приложения - "ThisIsASentenceWithCAPTIInIt"

То, что я хочу передать назад - «Это предложение с CAPTI в нем»

Что я получаю от моей модифицированной версии - «Это предложение с помощью CAPTIIn It»

Ответы [ 2 ]

0 голосов
/ 03 июня 2019

Это мое предложение:

DECLARE @s VARCHAR(100)='ThisIsASentenceWithCAPTIInIt';

WITH cte AS
(
    SELECT 1 AS Position
          ,@s AS Original
          ,CAST(SUBSTRING(@s,1,1) AS VARCHAR(MAX)) AS GrowingString
    UNION ALL
    SELECT cte.Position+1
          ,cte.Original
          ,CONCAT(cte.GrowingString 
          ,CurrentLetter
          ,CASE WHEN CurrentCapit=0 AND NextCapit=1 THEN ' ' ELSE 
                CASE WHEN CurrentCapit=1 AND NextCapit=1 AND ThirdCapit=0 THEN ' ' ELSE '' END END ) AS GrowingString
    FROM cte
    CROSS APPLY(SELECT SUBSTRING(@s,cte.Position+1,1) CurrentLetter
                      ,SUBSTRING(@s,cte.Position+2,1) NextLetter
                      ,SUBSTRING(@s,cte.Position+3,1)ThirdLetter) A
    CROSS APPLY(SELECT CASE WHEN ASCII(CurrentLetter) BETWEEN 65 AND 90 THEN 1 ELSE 0 END CurrentCapit
                      ,CASE WHEN ASCII(NextLetter) BETWEEN 65 AND 90 THEN 1 ELSE 0 END NextCapit
                      ,CASE WHEN ASCII(ThirdLetter) BETWEEN 65 AND 90 THEN 1 ELSE 0 END ThirdCapit) B
    WHERE cte.Position < LEN(@s)
)
SELECT TOP 1 GrowingString
FROM cte
ORDER BY Position DESC;

Идея вкратце:

Мы используем рекурсивный CTE.Простой подход будет просто читать строку символ за символом и будет возвращать всю строку в GrowingString в конце.Это будет то же самое, что и исходная строка.

Сложная часть: Где вставить пробелы?

Если текущая буква не заглавная, а следующая - нам нужен пробел.Это уж точно.Кроме того, встроенный CASE будет проверять, является ли текущая и следующая буква заглавной, но третья.В этом случае нам тоже нужно место.

0 голосов
/ 31 мая 2019

делать это в SQL Server - не лучший выбор.переписывание существующей строки может быть сложной задачей.

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

DECLARE @String    NVARCHAR(MAX) = 'ThisIsASentenceWithCAPTIInIt'
    --, @Len       INT         --  = LEN(@String)
      , @Delimiter CHAR(1)       = ' '
      , @Iterator  INT           = 1; --Don't put space to left of first even if it's a capital

DECLARE @retval nvarchar(max) = '';

WHILE @Iterator <= LEN(@String)
-- Iterate through string
    BEGIN
        -- Check if current character is Uppercase (lowercase = 0)
        IF PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator, 1) COLLATE Latin1_General_CS_AI) <> 0
        -- Do this if capital
            BEGIN
                -- check if the previous character is lowercase, if it is then add a space before the current character.
                IF(
                   (PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator - 1, 1) COLLATE Latin1_General_CS_AI) = 0
                    AND SUBSTRING(@String, @Iterator - 1, 1) <> ' '
                   )
                   OR PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator + 1, 1) COLLATE Latin1_General_CS_AI) = 0)
                    BEGIN
                        set @retval += ' ' ;
                        --SET @String = STUFF(@String, @Iterator, 0, @Delimiter);
                        --SET @Iterator+=1;
                END;
                -- check if the next character is lowercase, if it is then add a space before the current character.
                --Set @retval += SUBSTRING(@String, @Iterator, 1);
                --SET @Iterator+=1;
            END;
        ---- Don't care about current character being lowercase. Just continue iterating
        Set @retval += SUBSTRING(@String, @Iterator, 1);
        SET @Iterator+=1;
    END;
SET @retval = Ltrim(@retval);
SELECT @retval;
...