【组合字符和预组字符】

什么是组合字符?

UCS里有些编码点分配给了 组合字符.它们类似于打字机上的无间隔重音键. 单个的组合字符不是一个完整的字符. 它是一个类似于重音符或其他指示标记, 加在前一个字符后面. 因而, 重音符可以加在任何字符后面. 那些最重要的被加重的字符, 就象普通语言的正字法(orthographies of common languages)里用到的那种, 在 UCS 里都有自己的位置, 以确保同老的字符集的向后兼容性. 既有自己的编码位置, 又可以表示为一个普通字符跟随一个组合字符的被加重字符, 被称为 预作字符(precomposed characters). UCS 里的预作字符是为了同没有预作字符的旧编码, 比如 ISO 8859, 保持向后兼容性而设的. 组合字符机制允许在任何字符后加上重音符或其他指示标记, 这在科学符号中特别有用, 比如数学方程式和国际音标字母, 可能会需要在一个基本字符后组合上一个或多个指示标记.

组合字符跟随着被修饰的字符. 比如, 德语中的元音变音字符 ("拉丁大写字母A 加上分音符"), 既可以表示为 UCS 码 U+00C4 的预作字符, 也可以表示成一个普通 "拉丁大写字母A" 跟着一个"组合分音符":U+0041 U+0308 这样的组合. 当需要堆叠多个重音符, 或在一个基本字符的上面和下面都要加上组合标记时, 可以使用多个组合字符. 比如在泰国文中, 一个基本字符最多可加上两个组合字符.

 

以下文字来自维基百科:

 

组合字符

维基百科,自由的百科全书
字体排印学中, 组合字符 是用来改变其它字符所用的 字符。在拉丁文字中,最常见的组合字符为 附加符号(包含 重音号)。

统一码也包含许多预组字符,即事先将字符组好并赋予码位。所以有可能同时使用组合字符和预组字符。这导致了若要比较两个统一码字串或设计编码转换器时,需要先运行统一码等价性[1]

在统一码中,用于欧洲语言和国际音标的组合用附加符号为 U+0300–U+036F 。组合用附加符号亦存在统一码中的多个区块。在统一码中,附加符号总是加在主要字符之后。因此,有可能加入多个附加符号。直到 2006 ,只有少数软件能正确显示此类组合。

OpenType

OpenType则有ccmp区块,以定义字形是由其它组合字符所组合出来或可分解之。

统一码范围

  • 组合用附加符号(Combining Diacritical Marks) (0300–036F),由版本 1.0 始,陆续修改到 4.1。
  • 组合用附加符号补集(Combining Diacritical Marks Supplement) (1DC0–1DFF),版本 4.1 到 5.2。
  • 符号之组合用附加符号(Combining Diacritical Marks for Symbols) (20D0–20FF),由版本 1.0 开始,陆续修改到 5.1。
  • 组合用半角符号(Combining Half Marks) (FE20–FE2F),由版本 1.0 开始,在 5.2 中修正。

码点U+0346–034A 为国际音标符号

码点 U+034B–034E 为用于disordered speech的国际音标附加符号

  • U+034B  ͋  : nasal escape;
  • U+034C  ͌  : velopharyngeal friction;
  • U+034D  ͍  : labial spreading;
  • U+034E  ͎  : whistled articulation;

注记

  1. ^例如,当在做windows-1258和越南资讯交换标准代码之间的转换时,前者使用组合字符而后者使用大量预组字符。转换器若只是单纯地与统一码码做转换,则会导致混乱。

 

      统一码等价性

      维基百科,自由的百科全书
      为了和许多现存的标准能够相容, 统一码包含了许多特殊 字符。在这些字符中,有些在功能上会和其它字符或字符序列等价。因此,统一码将一些码位序列定义成相等的。统一码提供了两种等价概念:标准等价和相容等价。前者是后者的一个 子集。例如,字符 n 后接着 组合字符 ~ 会(标准和相容)等价于统一码 ñ。而 合字 ff 则只有相容等价于两个 f 字符。

      统一码正规化是文字正规化的一种形式,是指将彼此等价的序列转成同一列序。此序列在统一码标准中称作正规形式。对于每种等价概念,统一码又定义两种形式,一种是完全合成的,一种是完全分解的。因此,最后会有四种形式,其缩写分别为:NFC、NFD、NFKC、NFKD。对于统一码的文字处理程式而言,正规化是很重要的。因为它影响了比较、搜寻和排序的意义。

      等价概念

      标准等价

      统一码中标准等价的基础概念为字符的组成和分解的交互使用。合成指的是将简单的字符合并成较少的预组字符的过程,如字符 n 和组合字符 ~ 可以组成统一码 ñ 。分解则是反向过程,即将预组字符变回部件。

      标准等价是指保持视觉上和功能上的等价。例如,含附加符号字母被视为和分解后的字母及其附加符号是标准等价。换句话说,预组字符‘ü’和由 ‘u’ 及 ‘¨’ 所组成的序列是标准等价。相似地,统一码统合了一些希腊附加符号和外观与附加符号类似的标点符号。

      相容等价

      相容等价的范围较标准等价来得广。如果序列是标准等价的话就会是相容等价,反之则未必对。相容等价更关注在于纯文字的等1价,并把一些语义上的不同形式归结在一起。


      例如,上标数字和其所使用的数字是相容等价,但非标准等价。其理由为下标和上标形式虽然在某些时侯属于不同意义,但若应用程式将他们视为一样也是合理的(虽然视觉上可区分)。如此,在统一码富文件中,上标和下标就可以以比较不累赘地方式出现(见下一节)。

      全角和半角的片假名也是一种相容等价但不是标准等价。如同合字和其部件序列。其只有视觉上但没有语义上的区别。换句话说,作者通常没有特别宣称使用合字是一种意思,而不使用是另一种意思。相对地,这尽限于印刷上的选择。

      正规化

      文书处理软件在实作统一码字串的搜寻和排序时,须考虑到等价性的存在。如果没有此特性的话,使用者在搜寻时将无法找到在视觉上无法区分的字形。

      统一码提供了一个标准的正规化算法,可将所有相同的序列产生一个唯一的序列。 其等价准绳可以为标准的(NF)或相容的(NFK)。 既然可以任意选择等价类中的元素,对每一个等价标准有多个标准形式也是有可能的。 统一码为每一种等价准绳分别提供两种正规形式:合成用的 NFC 和 NFKC 以及分解用的 NFD 和 NFKD。 而不论是组合的或分解的形式,都会使用标准顺序,以此限制正规形式只有唯一形式。

      为了比较或搜寻统一码字串,软件可以使用合成或分解形式其中之一。 只要被比较或搜寻的字串使用的形式是相同的,哪种选择都没关系。 另一方面,等价概念的选择则会影响到搜寻结果。 譬如,有些合字如 ffi(U+FB03)、罗马数字如Ⅸ(U+2168),甚至是上标数字如⁵(U+2075)有其个别统一码码位。 标准正规形式并不会影响这些结果。 但相容正规形式会分解 ffi 成 f、f、i。所以搜寻U+0066(f)时,在 NFKC 中会成功,但在 NFC 则会失败。 同样地有在预组罗马数字 Ⅸ 中搜寻拉丁字母 I(U+0049)。类似地,“⁵”会转成“5” 。

      对于丰富文件格式的浏覧器,将上标转换成到基底线未必是好的,因为上标的资讯会因而消失。为了允许这种不同,统一码字符数据库句含了相容格式标签,其提供了相容转换的细节。[1] 在合字的情况下,这个标签只是 <compat> ,而在上标的情况下则为 <super>。丰富文件格式如超文件标示语言则会使用相容标签。例如,HTML 使用自订标签来将 “5” 放到上标位置。[2]

      正规形式

      统一码定义了四种正规形式。这些形式或其(转换)算法表列如下。所有的形式都会使用到标准顺序,好让结果序列能保证是等价类中的唯一形式。这些算法都是幂等转换,但因为 singletons 和标准顺序的关系,都不是单射。 此外,也没有一个形式在字串串接下会是封闭的,意味着在同一个正规形式下的两个字串串接,并不保证产生的是正规形式。 这会发生在当一个字串并不是以基础字符为开头或以其它中间或结尾字符为开头的字串附加到另一个字串时。

      NFD
      Normalization Form Canonical Decomposition
      以标准等价方式来分解
      NFC
      Normalization Form Canonical Composition
      以标准等价方式来分解,然后以标准等价重组之。若是singleton的话,重组结果有可能和分解前不同。
      NFKD
      Normalization Form Compatibility Decomposition
      以相容等价方式来分解
      NFKC
      Normalization Form Compatibility Composition
      以相容等价方式来分解,然后以标准等价重组之。

      有些码点经过正规转换后,是无法转换成之前的形式。换个方式说则是, singleton 都不会是正规形式。譬如,埃格斯特朗符号 U+212B(Å),在 NFC 中总是被代换成在视觉上相同的 U+00C5 (Å – 在上方带环的 A)。在 NFD 中,则会换成由 U+0041(A)和 U+030A(° – combining ring above)这两个字符所组成的序列。因此,没有一个正规函数是单射的。

      在统一码字符数据库中,singletons是指那些和其它单一字符有相同分解的字符。

      标准顺序

      标准顺序主要关注在结合符序列的顺序。这里将以附加符号做例子。不过,一般而言,附加符号不是结合字符且结合字符不是附加符号。

      统一码假设每个字符是一个结合类别 ,并赋予一个数字。非结合字符的类别值为 0 ,而结合字符则会是一个正值。要得到标准顺序,每个有非零值结合符的子串序要以稳定排序算法排序过。稳定排序是必要的,因为结合字符被假设会影响到排版,所以两个顺序不被视为相等。

      例如,越南语字母中的字符 ế(U+1EBF)同时具有尖音符抑扬符。它的标准分解是序列 U+0065(e)、U+0302(抑扬符)、U+0301(尖音符)。这两个重音的结合类别都是 230 ,所以 U+1EBF 不等同于U+0065 U+0301 U+0302 。

      并非所有结合序列都有预组(在前一例的最后一个可以化简成 U+00E9 U+0302),即使 NFC 会被结合字符所影响。

      因正规化不同而导致的错误

      当两个应用程式分享统一码资料,但却使用不同正规形式时,就有可能导致错误。 例如, Mac OS X 有许多物件是只能使用分解字符(因此,以 UTF-8 为编码又限定分解形式的统一码又被称为 "UTF8-MAC")。 在一特例中, OS X 错误处理用途而产生的组合字符和Samba 档案和打印分享软件(在复制档案时,会将分解过的字母替换成组合过的字母)混合使用时,会导致混淆和损坏资料。[3][4]应用程式若要避免此类问题,可以保留输入码点,然后只在程式内部使用自己的正规化形式。

       

      <think>好的,我现在需要帮助用户解决如何在编程中实现过滤组合字符串的功能。根据用户提供的引用内容,尤其是引用[3][4],这个问题涉及生成组合字符串并过滤掉包含屏蔽字符串所有字符的情况。 首先,我得理解问题要求。例如,输入“78”屏蔽字符串“ux”,数字7对应uv,8对应xw。生成的组合有ux、uw、vx、vw。需要过滤掉包含所有屏蔽字符字符串,即ux包含ux,所以被过滤,剩下的就是uw、vx、vw。 接下来,我需要考虑如何实现这个功能。步骤可能包括: 1. **建立数字到字符的映射**:比如7对应u、v,8对应x、w等。可能需要先定义每个数字对应的字符列表。 2. **生成所有可能的组合**:这类似于笛卡尔积的问题,每个数字对应的字符依次组合。例如,对于输入“78”,需要将7的每个字符与8的每个字符组合,得到四个结果。 3. **过滤不符合条件的组合**:需要检查每个生成的字符串是否包含屏蔽字符串的所有字符。如果包含,则剔除;否则保留。 然后,我需要考虑具体的实现方法。根据用户提供的引用,可能涉及字符串处理、循环、递归或者库函数的使用,比如Python中的itertools.product来处理笛卡尔积。另外,过滤部分需要检查生成的字符串是否包含屏蔽字符串中的每一个字符,可以使用集合操作,例如将生成的字符串转换为集合,然后判断是否包含屏蔽字符串的字符集合。 需要注意的是,屏蔽字符串中的每个字符都必须出现在组合字符串中才会被过滤。例如,屏蔽字符串是“ux”,那么只有当生成的字符串同时包含ux时才会被过滤掉。因此,在过滤条件中,需要检查屏蔽字符串的每个字符是否都是生成字符串的子集。 可能的实现步骤: - **步骤1**:定义每个数字对应的字符列表,比如数字映射表。 - **步骤2**:将输入的数字字符串转换为对应的字符列表的集合。例如,"78"转换为[['u','v'], ['x','w']]。 - **步骤3**:计算这些字符列表的笛卡尔积,生成所有可能的组合字符串。 - **步骤4**:对每个组合字符串,检查是否包含屏蔽字符串的所有字符。如果包含,则排除;否则保留。 - **步骤5**:输出剩余的字符串。 在代码实现上,Python中可以使用itertools.product来处理步骤3的笛卡尔积。步骤4可以用all()函数来检查每个屏蔽字符是否存在于组合字符串中。例如,对于屏蔽字符串中的每个字符char,如果char不在组合字符串中,则保留该组合;否则,如果所有字符都在其中,则过滤掉。 测试案例方面,用户提供的示例是输入“78”“ux”,输出应为uw、vx、vw。需要确保代码正确处理这种情况,并且能够处理更复杂的输入,比如多位数或不同的屏蔽字符串。 另外,需要考虑输入的有效性,比如数字是否在映射表中,屏蔽字符串是否为空等边缘情况。不过根据问题描述,可能暂时不需要处理这些,但代码中最好有基本的错误处理。 最后,根据引用[3][4]中的例子,可能需要将过滤条件设置为完全包含所有屏蔽字符的情况才被过滤,所以使用all()函数是正确的选择。同时,组合生成需要确保顺序正确,比如输入“78”生成的组合是7的字符在前,8的字符在后,如ux、uw等。 总结下来,代码的大致结构会是: 1. 定义数字到字符的映射。 2. 处理输入,拆解每个数字对应的字符列表。 3. 生成所有可能的组合字符串。 4. 过滤掉包含所有屏蔽字符组合。 5. 输出结果。 现在,我需要将这些步骤转化为具体的Python代码,并确保符合用户的要求,同时引用相关的参考资料。</think>### 过滤组合字符串的实现方法 #### 实现思路 1. **建立数字字符映射**:定义每个数字对应的候选字符列表 2. **生成笛卡尔积**:根据输入的数字字符串生成所有可能的组合 3. **过滤屏蔽条件**:排除包含屏蔽字符串所有字符的项 #### Python实现代码 ```python from itertools import product def filter_combinations(digit_str, block_str): # 定义数字到字符的映射关系 digit_map = { '2': ['a', 'b', 'c'], '3': ['d', 'e', 'f'], '4': ['g', 'h', 'i'], '5': ['j', 'k', 'l'], '6': ['m', 'n', 'o'], '7': ['p', 'q', 'r', 's'], '8': ['t', 'u', 'v'], '9': ['w', 'x', 'y', 'z'] } # 获取每个数字对应的候选字符 char_lists = [digit_map[d] for d in digit_str if d in digit_map] # 生成所有组合 combinations = [''.join(comb) for comb in product(*char_lists)] # 过滤包含屏蔽字符串所有字符组合 block_set = set(block_str) filtered = [ comb for comb in combinations if not block_set.issubset(comb) ] return filtered # 示例使用 print(filter_combinations('78', 'ux')) # 输出 ['uw', 'vx', 'vw'] ``` #### 关键步骤解析 1. **数字映射**:使用定义的`digit_map`字典存储数字与字符的对应关系[^3] 2. **笛卡尔积生成**:`product(*char_lists)`自动生成所有排列组合 3. **集合运算过滤**:`block_set.issubset(comb)`快速判断是否包含所有屏蔽字符[^4]
      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值