概述
Swift 语言是一门现代化、安全、强大且还算性感的语言。在去年 WWDC 24 中苹果正式推出了秃头码农们期待许久的 Swift 6.0,它进一步完善了 Swift 语言的语法和语义,并再接再厉——强化了现代化并发模型的安全性和灵活性。
这里我们不妨用 Swift 来验证一个实际世界中有趣的小疑问:汉语中到底有没有拼音首字母全部相同的 4 字成语呢?
在本篇博文中,您将学到如下内容:
- 枝节横生
- 尘埃落定
- “超乎想象”的结果
到底问题的谜底将会如何?结果绝对会让大家“始料不及”! 那还等什么呢?Let's go!!!;)
8. 枝节横生
不过先别忙,因为忙中会出错!
使用上面的逻辑会找出很多只有 1 个拼音的 4 字(或 4 字以上)的成语,这是怎么回事呢?
重厚寡言 (zhòng hòu guǎ yán),拼音个数: 1 质而不野 (zhì ér bù yě),拼音个数: 1 蒸沙为饭 (zhēng shā wéi fàn),拼音个数: 1 引吭高声(yǐn háng gāo shēng),拼音个数: 1 一朝千里(yī zhāo qiān lǐ),拼音个数: 1 一朝之患(yī zhāo zhī huàn),拼音个数: 1 悬车之年(xuán chē zhī nián),拼音个数: 1 悬崖绝壁(xuán yá jué bì),拼音个数: 1 休明盛世(xiū míng shèng shì),拼音个数: 1 修旧利废(xiū jiù lì fèi),拼音个数: 1 项庄舞剑,志在沛公(xiàng zhuāng wǔ jiàn,zhì zài pèi gōng),拼音个数: 1 橡茹藿歠(xiàng rú huò chuò),拼音个数: 1 同文共轨(tóng wén gòng guǐ),拼音个数: 1 水长船高(shuǐ zhǎng chuán gāo),拼音个数: 1 书不尽言(shū bù jìn yán),拼音个数: 1 情长纸短(qíng cháng zhǐ duǎn),拼音个数: 1 弃书捐剑(qì shū juān jiàn),拼音个数: 1 批亢抵巇(pī gāng dǐ xī),拼音个数: 1 泥古拘方(nì gǔ jū fāng),拼音个数: 1 泥名失实(nì míng shī shí),拼音个数: 1 风轻云淡(fēng qīng yún dàn),拼音个数: 1 粉骨捐躯(fěn gǔ juān qū),拼音个数: 1 粉骨糜躯(fěn gǔ mí qū),拼音个数: 1 粉面朱唇(fěn miàn zhū chún),拼音个数: 1 粉身灰骨(fěn shēn huī gǔ),拼音个数: 1 堤溃蚁孔(dī kuì yǐ kǒng),拼音个数: 1 沉厚寡言(chén hòu guǎ yán),拼音个数: 1 沉重寡言(chén zhòng guǎ yán),拼音个数: 1 长幼有序(zhǎng yòu yǒu xù),拼音个数: 1
可以看到,这些成语至少都包含 4 个字,但为什么对应的拼音却只有 1 个呢?
这是由于这些成语拼音的间隔都不是普通的空格,而是其它字符导致的。仔细检查可以发现,这里实际间隔字符序列二进制值为 0xe3、0x80、0x80(即 8 位整形数组[227, 128, 128])。
有的小伙伴们可能又会问了:你是怎么知道这些特殊“空格”编码实际二进制值的?很简单,我们做实验!
if pinyins.count == 1 {
print("找到拼音间隔不为简单空格(0x20): \(pinyins)")
let cString = idiomPinyin.cString(using: .utf8)!
for (i,cchar) in cString.enumerated() {
print("[\(i)]: \(String.init(format: "%02x", cchar))")
}
break
}
我们在上面的代码里将原字符串先转换为 C 字符串,然后打印出每个字符的字节码一窥究竟:
找到拼音间隔不为简单空格(0x20): ["zhòng hòu guǎ yán"] [0]: 7a [1]: 68 [2]: ffffffc3 [3]: ffffffb2 [4]: 6e [5]: 67 [6]: ffffffe3 [7]: ffffff80 [8]: ffffff80 [9]: 68 [10]: ffffffc3 [11]: ffffffb2 [12]: 75 [13]: ffffffe3 [14]: ffffff80 [15]: ffffff80 [16]: 67 [17]: 75 [18]: ffffffc7 [19]: ffffff8e [20]: ffffffe3 [21]: ffffff80 [22]: ffffff80 [23]: 79 [24]: ffffffc3 [25]: ffffffa1 [26]: 6e [27]: 00
经过与原字符串中的字符对比,我们可以轻松求出间隔字符的编码为:0xe3,0x80,0x80。
一种方法是将它们替换为普通的空格字符(0x20),然后再解析:
let pinyins = idiomPinyin.split(separator: " ")
if pinyins.count == 1 {
print("找到拼音间隔不为简单空格(0x20): \(pinyins)")
let pyData = idiomPinyin.data(using: .utf8)!
let fixedData = pyData.replacing([227,128,128], with: [32])
let fixedPyString = String(data: fixedData, encoding: .utf8)!
let fixedPy = fixedPyString.split(separator: " ")
print("FIXED![\(fixedPy.count)]: \(fixedPy)")
}
运行可以发现,我们又可以成功的找回这些成语的所有拼音啦:
找到拼音间隔不为简单空格(0x20): ["zhòng hòu guǎ yán"] FIXED![4]: ["zhòng", "hòu", "guǎ", "yán"] 找到拼音间隔不为简单空格(0x20): ["zhì ér bù yě"] FIXED![4]: ["zhì", "ér", "bù", "yě"] 找到拼音间隔不为简单空格(0x20): ["zhēng shā wéi fàn"] FIXED![4]: ["zhēng", "shā", "wéi", "fàn"] 找到拼音间隔不为简单空格(0x20): ["yǐn háng gāo shēng"] FIXED![4]: ["yǐn", "háng", "gāo", "shēng"] 找到拼音间隔不为简单空格(0x20): ["yī zhāo qiān lǐ"] FIXED![4]: ["yī", "zhāo", "qiān", "lǐ"] 找到拼音间隔不为简单空格(0x20): ["yī zhāo zhī huàn"] FIXED![4]: ["yī", "zhāo", "zhī", "huàn"] 找到拼音间隔不为简单空格(0x20): ["xuán chē zhī nián"] FIXED![4]: ["xuán", "chē", "zhī", "nián"] 找到拼音间隔不为简单空格(0x20): ["xuán yá jué bì"] FIXED![4]: ["xuán", "yá", "jué", "bì"] ...
9. 尘埃落定
转眼之间这些“难关”都被逐一攻克,我们离最后的胜利只差一步之遥。
接下来我们只需获取所有拼音的首字母,然后判断它们是否相等即可。简单的方法是用集合(Set)的唯一性来解决它:
var pinyinFirstChars = pinyins.map { $0.first! }
if Set(pinyinFirstChars).count == 1 {
// 若所有拼音首字母相同,则集合里只会留存 1 个元素!
}
现在,我们可以怡然自得的补全代码中最后一块拼图了:
var bingooCount = 0
let pinyins = idiomPinyin.split(separator: " ")
var pinyinFirstChars = pinyins.map { $0.first! }
if pinyins.count == 1 {
print("找到拼音间隔不为简单空格(0x20): \(pinyins)")
let pyData = idiomPinyin.data(using: .utf8)!
let fixedData = pyData.replacing([227,128,128], with: [32])
let fixedPyString = String(data: fixedData, encoding: .utf8)!
let fixedPy = fixedPyString.split(separator: " ")
print("FIXED![\(fixedPy.count)]: \(fixedPy)")
pinyinFirstChars = fixedPy.map { $0.first! }
}
if Set(pinyinFirstChars).count == 1 {
bingooCount += 1
print("[\(bingooCount)]BINGOOO: \(idiomName)(\(idiomPinyin)) - \(pinyinFirstChars)")
}
10. “超乎想象”的结果
运行代码,大家猜猜在这 3w+ 条成语中到底有多少个首字母完全相同的成语呢?
除去疑似重复的成语,我们一共找到了 38 个符合条件的成语:
[1]: 做张做致 (zuò zhāng zuò zhì) - ["z", "z", "z", "z"] [2]: 做张做智 (zuò zhāng zuò zhì) - ["z", "z", "z", "z"] [3]: 自作主张 (zì zuò zhǔ zhāng) - ["z", "z", "z", "z"] [4]: 捉贼捉赃 (zhuō zéi zhuō zāng) - ["z", "z", "z", "z"] [5]: 捉贼捉脏 (zhuō zéi zhuō zāng) - ["z", "z", "z", "z"] [6]: 知足知止 (zhī zú zhī zhǐ) - ["z", "z", "z", "z"] [7]: 真赃真贼 (zhēn zāng zhēn zéi) - ["z", "z", "z", "z"] [8]: 隐隐约约(yǐn yǐn yuē yuē) - ["y", "y", "y", "y"] [9]: 遗音余韵(yí yīn yú yùn) - ["y", "y", "y", "y"] [10]: 一吟一咏(yī yīn yī yǒng) - ["y", "y", "y", "y"] [11]: 燕燕莺莺(yàn yàn yīng yīng) - ["y", "y", "y", "y"] [12]: 惺惺惜惺(xīng xīng xī xīng) - ["x", "x", "x", "x"] [13]: 惺惺相惜(xīng xīng xiāng xī) - ["x", "x", "x", "x"] [14]: 伈伈睍睍(xǐn xǐn xiàn xiàn) - ["x", "x", "x", "x"] [15]: 吞吞吐吐(tūn tūn tǔ tǔ) - ["t", "t", "t", "t"] [16]: 忑忑忐忐(tè tè tǎn tǎn) - ["t", "t", "t", "t"] [17]: 忐忐忑忑(tǎn tǎn tè tè) - ["t", "t", "t", "t"] [18]: 顺时随俗(shùn shí suí sú) - ["s", "s", "s", "s"] [19]: 适俗随时(shì sú suí shí) - ["s", "s", "s", "s"] [20]: 生生世世(shēng shēng shì shì) - ["s", "s", "s", "s"] [21]: 生生死死(shēng shēng sǐ sǐ) - ["s", "s", "s", "s"] [22]: 三三四四(sān sān sì sì) - ["s", "s", "s", "s"] [23]: 扭扭捏捏(niǔ niǔ niē niē) - ["n", "n", "n", "n"] [24]: 袅袅娜娜(niǎo niǎo nuó nuó) - ["n", "n", "n", "n"] [25]: 渺渺茫茫(miǎo miǎo máng máng) - ["m", "m", "m", "m"] [26]: 历历落落(lì lì luò luò) - ["l", "l", "l", "l"] [27]: 磊磊落落(lěi lěi luò luò) - ["l", "l", "l", "l"] [28]: 屦及剑及(jù jí jiàn jí) - ["j", "j", "j", "j"] [29]: 斤斤计较(jīn jīn jì jiào) - ["j", "j", "j", "j"] [30]: 将计就计(jiāng jì jiù jì) - ["j", "j", "j", "j"] [31]: 剑及屦及(jiàn jí jù jí) - ["j", "j", "j", "j"] [32]: 将机就机(jiāng jī jiù jī) - ["j", "j", "j", "j"] [33]: 将机就计(jiāng jī jiù jì) - ["j", "j", "j", "j"] [34]: 驾肩接迹(jià jiān jiē jì) - ["j", "j", "j", "j"] [35]: 昏昏浩浩(hūn hūn hào hào) - ["h", "h", "h", "h"] [36]: 贩夫贩妇(fàn fū fàn fù) - ["f", "f", "f", "f"] [37]: 颠颠倒倒(diān diān dǎo dǎo) - ["d", "d", "d", "d"] [38]: 啛啛喳喳(cuì cuì chā chā) - ["c", "c", "c", "c"]
看来我大中华成语文化真乃泛浩摩苍,竟然有这么多读起来朗朗上口的成语,呜呼快哉,棒棒哒!
这个结果小伙伴们之前想到了吗?大家还能找到其它拼音首字母完全相同的 4 字成语吗?如果有请大家在文后恣意砌楼给我们意外惊喜。
至此,我们已经完全解决了博文开头那个问题!小伙伴们赶快给自己一个大大的赞吧!么么哒!😘
总结
在本篇博文中,我们为 Swift 语言实现查找拼音首字母全部相同的 4 字成语这个小任务画上了一个完美的句号,很赞哦!
感谢观赏,再会啦!8-)