SQL-leetcode—3374. 首字母大写 II

3374. 首字母大写 II

表:user_content

±------------±--------+

| Column Name | Type |

±------------±--------+

| content_id | int |

| content_text| varchar |

±------------±--------+

content_id 是这张表的唯一主键。

每一行包含一个不同的 ID 以及对应的文本内容。

编写一个解决方案来根据下面的规则来转换 content_text 列中的文本:

将每个单词的 第一个字母 转换为 大写,其余字母 保持小写。

特殊处理包含特殊字符的单词:

对于用短横 - 连接的词语,两个部份 都应该 大写(例如,top-rated → Top-Rated)

所有其他 格式 和 空格 应保持 不变

返回结果表同时包含原始的 content_text 以及根据上述规则修改后的文本。

结果格式如下例所示。

示例:

输入:

user_content 表:

±-----------±--------------------------------+

| content_id | content_text |

±-----------±--------------------------------+

| 1 | hello world of SQL |

| 2 | the QUICK-brown fox |

| 3 | modern-day DATA science |

| 4 | web-based FRONT-end development |

±-----------±--------------------------------+

输出:

±-----------±--------------------------------±--------------------------------+

| content_id | original_text | converted_text |

±-----------±--------------------------------±--------------------------------+

| 1 | hello world of SQL | Hello World Of Sql |

| 2 | the QUICK-brown fox | The Quick-Brown Fox |

| 3 | modern-day DATA science | Modern-Day Data Science |

| 4 | web-based FRONT-end development | Web-Based Front-End Development |

±-----------±--------------------------------±--------------------------------+

解释:

对于 content_id = 1:

每个单词的首字母都是大写的:"Hello World Of Sql"

对于 content_id = 2:

包含的连字符词 "QUICK-brown" 变为 "Quick-Brown"

其它单词遵循普通的首字母大写规则

对于 content_id = 3:

连字符词 "modern-day" 变为 "Modern-Day"

"DATA" 转换为 "Data"

对于 content_id = 4:

包含两个连字符词:"web-based" → "Web-Based"

以及 "FRONT-end" → "Front-End"

题解

  1. 要考虑怎么把首字母切分出来,然后连接
    substring,concat,lower、upper,然后就慢慢转化呗
  2. 技术上不好处理,可以把问题前置,比如用代码处理,不用sql

方法一

复制代码
-- 文本处理函数集合:将文本转换为首字母大写格式(支持含短横线的单词)
SELECT
content_id,
content_text AS original_text,
(
    -- 主查询:处理每个单词并重新连接成文本
    SELECT GROUP_CONCAT(
    CASE
    -- 处理含短横线的复合词(如 "quick-brown" → "Quick-Brown")
    WHEN INSTR(word, '-') > 0 THEN
    CONCAT(
    UPPER(LEFT(SUBSTRING_INDEX(word, '-', 1), 1)), -- 第一部分首字母大写
    LOWER(SUBSTRING(SUBSTRING_INDEX(word, '-', 1), 2)), -- 其余小写
    '-', -- 保留短横线
    UPPER(LEFT(SUBSTRING_INDEX(word, '-', -1), 1)), -- 第二部分首字母大写
    LOWER(SUBSTRING(SUBSTRING_INDEX(word, '-', -1), 2)) -- 其余小写
    )
    -- 处理普通单词(如 "the" → "The")
    ELSE
    CONCAT(UPPER(LEFT(word, 1)), LOWER(SUBSTRING(word, 2)))
    END
    SEPARATOR ' ') -- 用空格连接处理后的单词
    FROM (
    -- 子查询:将文本按空格拆分为单词(最多支持6个单词,可扩展)
    SELECT TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(LOWER(content_text), ' ', n), ' ', -1)) AS word
    FROM (SELECT content_text FROM user_content WHERE content_id = t.content_id) AS c
    JOIN (
    SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL
    SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 -- 扩展此范围以支持更多单词
    ) AS nums
    ON CHAR_LENGTH(LOWER(content_text)) - CHAR_LENGTH(REPLACE(LOWER(content_text), ' ', '')) >= nums.n - 1
    ) AS words
) AS converted_text
FROM user_content t;

方法二

复制代码
WITH RECURSIVE cte_split AS (
  -- 初始分割文本,将每个单词逐一提取
  SELECT
    content_id,
    @x := content_text AS original_text,
    @dash := LOCATE('-', @x) AS first_dash,
    @space := LOCATE(' ', @x) AS fist_space,
    @sec := CASE
        WHEN @dash <> '0' AND @space <> '0' THEN
            LEAST(CAST(@space AS UNSIGNED), CAST(@dash AS UNSIGNED))
        WHEN @dash = '0' AND @space = '0' THEN
            LENGTH(@x)
        ELSE
            GREATEST(CAST(@space AS UNSIGNED), CAST(@dash AS UNSIGNED))
    END AS separate_loc,
    LEFT(@x, CAST(@sec AS UNSIGNED)) AS word,
    SUBSTRING(@x, CAST(@sec AS UNSIGNED) + 1) AS remaining_text,
    0 AS word_order -- 跟踪单词的顺序
  FROM user_content
  UNION ALL
  -- 递归分割剩余文本中的单词
  SELECT
    content_id,
    original_text,
    @dash := LOCATE('-', remaining_text) AS first_dash,
    @space := LOCATE(' ', remaining_text) AS fist_space,
    @sec := CASE
        WHEN @dash <> '0' AND @space <> '0' THEN
            LEAST(CAST(@space AS UNSIGNED), CAST(@dash AS UNSIGNED))
        WHEN @dash = '0' AND @space = '0' THEN
            LENGTH(remaining_text)
        ELSE
            GREATEST(CAST(@space AS UNSIGNED), CAST(@dash AS UNSIGNED))
    END AS separate_loc,
    LEFT(remaining_text, CAST(@sec AS UNSIGNED)) AS word,
    SUBSTRING(remaining_text, CAST(@sec AS UNSIGNED) + 1) AS remaining_text,
    word_order + 1 -- 跟踪单词的顺序
  FROM cte_split
  WHERE remaining_text <> ''
),
cte_transformed AS (
  SELECT
    content_id,
    original_text,
    word_order,
    CONCAT(
        UPPER(SUBSTRING(word, 1, 1)),
        LOWER(SUBSTRING(word, 2))
    )
    AS transformed_word
  FROM cte_split
),
cte_reconstructed AS (
  -- 重建文本,将转换后的单词重新组合
  SELECT
    content_id,
    original_text,
    GROUP_CONCAT(transformed_word ORDER BY word_order SEPARATOR '') AS converted_text
  FROM cte_transformed
  GROUP BY content_id
)
SELECT
  content_id,
  original_text,
  converted_text
FROM cte_reconstructed;
相关推荐
大白的编程日记.5 小时前
【Linux学习笔记】线程概念和控制(二)
linux·笔记·学习
jerryinwuhan5 小时前
VIM和Linux命令速查表
linux·编辑器·vim
小白银子5 小时前
零基础从头教学Linux(Day 45)
linux·运维·junit·openresty
穷人小水滴6 小时前
笔记本 光驱 的内部结构及用法: 应急系统启动 (恢复) 光盘 (DVD+R/RW)
linux
半梦半醒*7 小时前
nginx反向代理和负载均衡
linux·运维·nginx·centos·tomcat·负载均衡
青草地溪水旁8 小时前
pthread_create详解:打开多线程编程的大门
linux·c/c++
小欣加油8 小时前
leetcode 1863 找出所有子集的异或总和再求和
c++·算法·leetcode·职场和发展·深度优先
A-刘晨阳9 小时前
Linux安装centos8及基础配置
linux·运维·服务器·操作系统·centos8
不老刘9 小时前
macOS/Linux ClaudeCode 安装指南及 Claude Sonnet 4.5 介绍
linux·macos·ai编程·claude·vibecoding
野熊佩骑10 小时前
一文读懂Redis之数据持久化
linux·运维·数据库·redis·缓存·中间件·centos