如何确定字符串显示的宽度

2020-05-17 14:32:02 +08:00
 songdg

例如 a = 'PM2.5' b = '地下管道' c = '空铁 WIFI',a 、b 、c 的宽度分别为 5 、8 、8,字母、数字的宽度为 1,汉字的宽度为 2 。用 len 函数得到的结果为 5 、4 、6 ;用 sys.getsizeof 得到的结果为 54 、82 、86,当字符串中含有混合字符时也不能用来推导显示宽度。请教还有没有其他方法。

4217 次点击
所在节点    Python
21 条回复
codehz
2020-05-17 14:35:45 +08:00
用 freetype 的 api 真实可以取得各种测量属性,当然,需要指定字体
xcstream
2020-05-17 14:43:09 +08:00
用等宽字体 判断中英文
ClericPy
2020-05-17 14:50:22 +08:00
暂时能想到的就只有正则出中文字数... len + len_中
secondwtq
2020-05-17 14:53:20 +08:00
这么复杂的问题你确定能在中文社区问出答案来么……
0x5f
2020-05-17 15:04:03 +08:00
如果是获取显示在图片上的宽度话 pil 库里有个 ImageFont.getsize()可以返回渲染后文字长宽
JCZ2MkKb5S8ZX9pq
2020-05-17 15:52:43 +08:00
我自己在用的是这个

width = (len(string) + len(string.encode('utf-8'))) // 2 # py3

前置还要移掉点 anis 之类的玩意儿,中日英目前用下来还好,日文小字也算 2 。
但是类似西班牙语法语那种带小尾巴的,unicode 有种写法是尾巴单独用一个字符,那个也许会有问题。
JCZ2MkKb5S8ZX9pq
2020-05-17 15:56:55 +08:00
@ClericPy
看看我上面这个,利用了编码之后中文 1 变 3 的特性,平时主要处理中英文还好,看看会有什么问题吗?

@songdg
另外我想起来类似 preetrytable 之类的模块,好像中文宽度都给处理过了,有兴趣也可以直接看看人家源码。
lithbitren
2020-05-17 15:59:44 +08:00
只看中英文和常用符号还好,加上其他语言符号是真 jb 复杂
JCZ2MkKb5S8ZX9pq
2020-05-17 16:03:25 +08:00
另外我上面说的都是我在程序里打印结果,然是是等宽字体的情况下的占位数。
如果是显示的话,要看显示在什么地方,以及用什么字体吧。lz 可以把问题再具体一点。
图片的话上面提到 pil 可以,截屏去拿也是个办法。
终端的话因为是等宽的,且行宽可测所以推测行数也是可以的。
justfortest
2020-05-17 18:05:35 +08:00
这是个复杂的问题
jin7
2020-05-17 19:13:23 +08:00
用 pyqt5/pyside2 就行了 很容易计算宽度
XIVN1987
2020-05-17 21:56:35 +08:00
In [11]: s = '空铁 WIFI'

In [12]: [ord(c) for c in s]
Out[12]: [31354, 38081, 87, 73, 70, 73]

In [13]: [1 if ord(c) < 0x80 else 2 for c in s]
Out[13]: [2, 2, 1, 1, 1, 1]

In [14]: sum([1 if ord(c) < 0x80 else 2 for c in s])
Out[14]: 8
lithbitren
2020-05-17 22:06:14 +08:00
全角和半角符号的编码范围不是连续的,一个比较符的实现可能还是有 bug 的。
Kisesy
2020-05-17 22:12:58 +08:00
if unicodedata.east_asian_width(char) in ('F', 'W'):
width = width + 2
else:
width = width + 1
XiaoxiaoPu
2020-05-17 22:28:12 +08:00
有个现成的库,用了很久了 wcwidth
aihimmel
2020-05-17 22:44:15 +08:00
不要简单推定字符宽度
"لا"
上面这个是两个字符但是打印出来只有 1 的宽度,确定宽度最好还是渲染出来再取宽度
songdg
2020-05-19 09:17:02 +08:00
@codehz 谢谢,有必要还是要试一下。
songdg
2020-05-19 09:18:43 +08:00
@JCZ2MkKb5S8ZX9pq 谢谢,基本上解决了我的问题。
songdg
2020-05-19 09:20:10 +08:00
@Kisesy 谢谢帮助。
songdg
2020-05-19 09:21:45 +08:00
@XIVN1987 谢谢帮助。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/672564

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX