是否有一些列表或算法可以实现以下操作:
- 给定 Ú、Ù 或 Ü,返回英文字母 U
- 给定英文字母 U,返回所有类似 U 的字符的列表
更新:
如果您正在使用 Ruby,则可使用 gem unicode-confusable 来帮助处理某些情况。
非常不清楚您想要做什么。
有些字符的规范分解都以相同的基础字符开头:e、é、ê、ë、ē、ĕ、ė、ę、ě、ȅ、ȇ、ȩ、ḕ、ḗ、ḙ、ḛ、ḝ、ẹ、ẻ、ẽ、ế、ề、ể、ễ、ệ、e̳、…或s、ś、ŝ、ş、š、ș、ṡ、ṣ、ṥ、ṧ、ṩ、…。
有些字符的兼容分解都包含特定字符:ᵉ、ₑ、ℯ、ⅇ、⒠、ⓔ、㋍、㋎、e、…或s、ſ、ˢ、ẛ、₨、℁、⒮、ⓢ、㎧、㎨、㎮、㎯、㎰、㎱、㎲、㎳、㏛、ſt、st、s、…或R、ᴿ、₨、ℛ、ℜ、ℝ、Ⓡ、㏚、R、…。
在某些字体中会出现 长得很像的 字符,例如:ß、β 和 ϐ,或者 3、Ʒ、Ȝ、ȝ、ʒ、ӡ和 ᴣ,或者ɣ、ɤ和γ,或者 F、Ϝ和 ϝ,或者 B、Β和В,或者∅、○、0、O、০、੦、౦和૦,或者 1、l、I、Ⅰ、ᛁ、|、ǀ和∣等等。
忽略大小写后相同的字符,例如 s、S和ſ,或者 ss、Ss、SS、ß和ẞ等等。
所有具有相同的 数字值 的字符,例如所有这些字符都为数字 1:1¹١۱߁१১੧૧୧௧౧౹౼೧൧๑໑༡၁႑፩១៱᠑᥇᧑᧚᪁᪑᭑᮱᱁᱑₁⅟ ① ⑴ ⒈ ⓵ ❶➀➊꘡꣑꤁꧑꩑꯱ Ⅰⅰꛦ㆒㈠㊀等等。
具有相同主要排序规则的字符,例如以下这些字母都与d相同: DdÐðĎďĐđ◌ͩᴰᵈᶞ◌ᷘ◌ᷙḊḋḌḍḎḏḐḑḒḓⅅⅆⅮⅾ Ⓓ ⓓ ꝹꝺDd。请注意,其中一些字符无法通过任何形式的分解访问,只能通过DUCET/UCA值进行比较;例如,常见的 ð 或新的 ꝺ 只能通过主要的UCA强度比较等同于 d;类似地,ƶ 和 z、ȼ 和 c等也是如此。
在某些语境中完全相同的字符,例如 æ 和 ae, or ä 和 ae, or ä 和 aa, 或 MacKinley 和 McKinley, …。请注意,语境可能会有很大的影响,因为在某些语境中,c 和 ç 都是相同的字符,而在其他语境中不是;n 和 ñ、a 和 á 和 ã 等情况也是如此。
其中一些可以处理,但有些无法处理。全部需要根据不同需求采用不同的方法。
你真正的目标是什么?
这种方法并不适用于所有情况,但是消除大多数重音的一种方法是将字符转换为其分解形式,然后丢弃组合重音符:
# coding: utf8
import unicodedata as ud
s=u'U, Ù, Ú, Û, Ü, Ũ, Ū, Ŭ, Ů, Ű, Ų, Ư, Ǔ, Ǖ, Ǘ, Ǚ, Ǜ, Ụ, Ủ, Ứ, Ừ, Ử, Ữ, Ự'
print ud.normalize('NFD',s).encode('ascii','ignore')
U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U
要查找重音字符,可以使用类似以下的方法:
import unicodedata as ud
import string
def asc(unichr):
return ud.normalize('NFD',unichr).encode('ascii','ignore')
U = u''.join(unichr(i) for i in xrange(65536))
for c in string.letters:
print u''.join(u for u in U if asc(u) == c)
aàáâãäåāăąǎǟǡǻȁȃȧḁạảấầẩẫậắằẳẵặ
bḃḅḇ
cçćĉċčḉ
dďḋḍḏḑḓ
eèéêëēĕėęěȅȇȩḕḗḙḛḝẹẻẽếềểễệ
fḟ
:
etc.
为什么不试着用类似这样的方式来比较字形呢?
package similarglyphcharacterdetector;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class SimilarGlyphCharacterDetector {
static char[] TEST_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890".toCharArray();
static BufferedImage[] SAMPLES = null;
public static BufferedImage drawGlyph(Font font, String string) {
FontRenderContext frc = ((Graphics2D) new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY).getGraphics()).getFontRenderContext();
Rectangle r= font.getMaxCharBounds(frc).getBounds();
BufferedImage res = new BufferedImage(r.width, r.height, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g = (Graphics2D) res.getGraphics();
g.setBackground(Color.WHITE);
g.fillRect(0, 0, r.width, r.height);
g.setPaint(Color.BLACK);
g.setFont(font);
g.drawString(string, 0, r.height - font.getLineMetrics(string, g.getFontRenderContext()).getDescent());
return res;
}
private static void drawSamples(Font f) {
SAMPLES = new BufferedImage[TEST_CHARS.length];
for (int i = 0; i < TEST_CHARS.length; i++)
SAMPLES[i] = drawGlyph(f, String.valueOf(TEST_CHARS[i]));
}
private static int compareImages(BufferedImage img1, BufferedImage img2) {
if (img1.getWidth() != img2.getWidth() || img1.getHeight() != img2.getHeight())
throw new IllegalArgumentException();
int d = 0;
for (int y = 0; y < img1.getHeight(); y++) {
for (int x = 0; x < img1.getWidth(); x++) {
if (img1.getRGB(x, y) != img2.getRGB(x, y))
d++;
}
}
return d;
}
private static int nearestSampleIndex(BufferedImage image, int maxDistance) {
int best = Integer.MAX_VALUE;
int bestIdx = -1;
for (int i = 0; i < SAMPLES.length; i++) {
int diff = compareImages(image, SAMPLES[i]);
if (diff < best) {
best = diff;
bestIdx = i;
}
}
if (best > maxDistance)
return -1;
return bestIdx;
}
public static void main(String[] args) throws Exception {
Font f = new Font("FreeMono", Font.PLAIN, 13);
drawSamples(f);
HashMap<Character, StringBuilder> res = new LinkedHashMap<Character, StringBuilder>();
for (char c : TEST_CHARS)
res.put(c, new StringBuilder(String.valueOf(c)));
int maxDistance = 5;
for (int i = 0x80; i <= 0xFFFF; i++) {
char c = (char)i;
if (f.canDisplay(c)) {
int n = nearestSampleIndex(drawGlyph(f, String.valueOf(c)), maxDistance);
if (n != -1) {
char nc = TEST_CHARS[n];
res.get(nc).append(c);
}
}
}
for (Map.Entry<Character, StringBuilder> entry : res.entrySet())
if (entry.getValue().length() > 1)
System.out.println(entry.getValue());
}
}
输出:
AÀÁÂÃÄÅĀĂĄǍǞȀȦΆΑΛАѦӒẠẢἈἉᾸᾹᾺᾼ₳Å
BƁƂΒБВЬḂḄḆ
CĆĈĊČƇΓЄГСὉℂⅭ
...
I
、l
和1
,或者0
、o
和O
是不同的,同时仍然说所有那些像B
一样的东西都是相同的。 - OrangeDog
confusables
几乎是完全相似的,而不是带重音符号的版本。(例如:) - karatedog