-
Notifications
You must be signed in to change notification settings - Fork 0
/
上字系聯.py
68 lines (57 loc) · 3.37 KB
/
上字系聯.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 系聯等價於計算機科學中圖的連通分量問題
# 故此處引入相關函數庫 `networkx`,用於創建無向圖及計算圖的連通分量
# 安裝方法:`pip install networkx`
import networkx as nx
# 爲了找出反切上字的上字,首先需要創建 (字頭, 音韻地位) 到反切上字的映射
# 創建此映射後,只需要提供字頭和音韻地位的信息,就可以得到字頭對應的反切上字
# 因此,如果提供反切上字和反切上字音韻地位的信息,就可以得到反切上字的上字
# 之所以需要提供音韻地位的信息,是因爲對於多音字而言,
# 同一個字的不同讀音可能對應不同的反切上字
# 此處創建一個空的 `dict`,用於存儲這一映射關係
d字頭_最簡描述2上字 = {}
# 開啓廣韻表
# 由於廣韻表格式未來可能發生變動,使用時需要固定版本號
# 所用版本爲 https://raw.githubusercontent.com/nk2028/qieyun-data/9675d039f953393e248212354ea764eb3aad8dc3/%E9%9F%BB%E6%9B%B8/%E5%BB%A3%E9%9F%BB.csv
with open('廣韻.csv') as f:
# 跳過第一行,第一行爲標題行,無需解析
next(f)
# 對於後續的每一行
for line in f:
# 去除行尾的換行符,然後以逗號分開
小韻號, 韻部原貌, 最簡描述, 反切覈校前, 反切, 字頭覈校前, 字頭, 釋義, 釋義補充, 圖片id = line.rstrip('\n').split(',')
# 在廣韻表中,反切一欄的內容若與反切覈校前的內容相同,
# 爲降低數據冗餘,將這一欄的內容刪除,相同內容僅存儲一次
# 字頭一欄同理
# 此處恢復刪除的內容
反切 = 反切 or 反切覈校前
字頭 = 字頭 or 字頭覈校前
# 排除沒有反切的小韻
# 若沒有反切,則反切字符串的長度爲 0
if len(反切) == 2:
# 解析反切,得到反切上字和下字
上字, 下字 = 反切
# 將一條 (字頭, 音韻地位) 到反切上字的映射關係加入之前創建的 `dict` 中
d字頭_最簡描述2上字[字頭, 最簡描述] = 上字
# 創建一個空的無向圖
G = nx.Graph()
# 開啓廣韻反切音韻地位表
with open('廣韻反切音韻地位表.csv') as f:
# 跳過第一行,第一行爲標題行,無需解析
next(f)
# 對於後續的每一行
for line in f:
# 去除行尾的換行符,然後以逗號分開
小韻號, 小韻首字, 上字, 下字, 被切字音韻描述, 上字音韻描述們, 下字音韻描述們 = line.rstrip('\n').split(',')
# 根據 (字頭, 音韻地位) 到反切上字的映射關係,
# 找出反切上字的所有可能的上字,即上字的上字
上字的上字們 = {d字頭_最簡描述2上字[上字, 上字音韻描述] for 上字音韻描述 in 上字音韻描述們.split('/')}
# 只處理上字的上字唯一的情況
if len(上字的上字們) == 1:
# 獲得上字的上字
上字的上字 = next(iter(上字的上字們))
# 將 (上字, 上字的上字) 這一條邊加入無向圖中
G.add_edge(上字, 上字的上字)
# 輸出無向圖的所有連通分量
for k, v in enumerate(nx.connected_components(G), 1):
# 此處使用 `sorted` 排序後再輸出,可以保證每次輸出的順序是相同的
print(k, ''.join(sorted(v)))