鱼C论坛

 找回密码
 立即注册
查看: 17563|回复: 5

[已解决]python 中英文混合格式化输出对齐

[复制链接]
发表于 2015-12-28 00:37:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
写了一个小程序本来输出对不对齐不影响结果:(由于代码一直在修改,有点乱就不全贴出来了)
我用的格式化化输出:
  1. print('%-25s %-35s' % (a,b))
复制代码

结果:
  1. 步走寻常路                     1736368                             
  2. Elvis                     1537433
复制代码

因为python3中默认unicode,汉字占的字节数不定,所以这里没法对齐。
我首先想到的是:
中间不是用空格填充嘛,先计算每一行汉字的长度length=len(line) 25- length就得到了这一行中间的空格数count  直接:" "*count
结果还是差不多,明白len()计算的是字符数,然后又试了下str.__sizeof__(),发现汉字字节数较大,还不相同,因此无法确定前面汉字字节范围,又没法操作了。

然后开始百度,找到一个:http://www.th7.cn/Program/Python/201407/245434.shtml 这博客里最后的效果倒出来了,但那代码没看懂。
求大神指点下方向
最佳答案
2015-12-28 13:14:40
中英文混排时对齐是比较麻烦的,一个先决条件是必须是等宽字体,每个汉字占2个英文字符的位置。
用print的格式输出是无法完成的。另一个途径就是用字符串的方法ljust, rjust, center先填充空格。但这些方法是以len()为基准的,即1个英文字符长度为1,1个汉字字符长度为3(uft-8编码),无法满足我们的要求。
我写了一个函数,可供参考。核心是利用字符的gb2312编码正好长度汉字是2,英文是1。
  1. def alignment(str1, space, align = 'left'):
  2.     length = len(str1.encode('gb2312'))
  3.     space = space - length if space >=length else 0
  4.     if align == 'left':
  5.         str1 = str1 + ' ' * space
  6.     elif align == 'right':
  7.         str1 = ' '* space +str1
  8.     elif align == 'center':
  9.         str1 = ' ' * (space //2) +str1 + ' '* (space - space // 2)
  10.     return str1
  11. #举例
  12. print('1234567890'*6) #打印标尺
  13. str1 = 'abc1234'
  14. str2 = 'abc中文'
  15. print(alignment(str2, 10, 'center'), alignment(str1, 10), sep = '')
  16. #print本身就会在每个字符串之间加个空格,这里去掉

  17.    
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2015-12-28 13:14:40 | 显示全部楼层    本楼为最佳答案   
中英文混排时对齐是比较麻烦的,一个先决条件是必须是等宽字体,每个汉字占2个英文字符的位置。
用print的格式输出是无法完成的。另一个途径就是用字符串的方法ljust, rjust, center先填充空格。但这些方法是以len()为基准的,即1个英文字符长度为1,1个汉字字符长度为3(uft-8编码),无法满足我们的要求。
我写了一个函数,可供参考。核心是利用字符的gb2312编码正好长度汉字是2,英文是1。
  1. def alignment(str1, space, align = 'left'):
  2.     length = len(str1.encode('gb2312'))
  3.     space = space - length if space >=length else 0
  4.     if align == 'left':
  5.         str1 = str1 + ' ' * space
  6.     elif align == 'right':
  7.         str1 = ' '* space +str1
  8.     elif align == 'center':
  9.         str1 = ' ' * (space //2) +str1 + ' '* (space - space // 2)
  10.     return str1
  11. #举例
  12. print('1234567890'*6) #打印标尺
  13. str1 = 'abc1234'
  14. str2 = 'abc中文'
  15. print(alignment(str2, 10, 'center'), alignment(str1, 10), sep = '')
  16. #print本身就会在每个字符串之间加个空格,这里去掉

  17.    
复制代码

评分

参与人数 1荣誉 +5 鱼币 +3 收起 理由
~风介~ + 5 + 3 热爱鱼C^_^

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-28 20:20:26 | 显示全部楼层
冬雪雪冬 发表于 2015-12-28 13:14
中英文混排时对齐是比较麻烦的,一个先决条件是必须是等宽字体,每个汉字占2个英文字符的位置。
用print的 ...

谢谢,我明白了你的意思。但是由于我的文件中的数据不仅限于中英文,有些符号gb2312无法解码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-12-28 20:27:26 | 显示全部楼层
小小大鱼 发表于 2015-12-28 20:20
谢谢,我明白了你的意思。但是由于我的文件中的数据不仅限于中英文,有些符号gb2312无法解码

这样不好办,建议用\t分隔
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-28 22:08:35 | 显示全部楼层
冬雪雪冬 发表于 2015-12-28 20:27
这样不好办,建议用\t分隔

目前只能这样了,我内功还不够,还要多修练。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-4-3 10:58:53 | 显示全部楼层
1. 获取字符串宽度
  1. def get_str_width(string):
  2.     widths = [
  3.       (126,  1), (159,  0), (687,   1), (710,  0), (711,  1),
  4.       (727,  0), (733,  1), (879,   0), (1154, 1), (1161, 0),
  5.       (4347,  1), (4447,  2), (7467,  1), (7521, 0), (8369, 1),
  6.       (8426,  0), (9000,  1), (9002,  2), (11021, 1), (12350, 2),
  7.       (12351, 1), (12438, 2), (12442,  0), (19893, 2), (19967, 1),
  8.       (55203, 2), (63743, 1), (64106,  2), (65039, 1), (65059, 0),
  9.       (65131, 2), (65279, 1), (65376,  2), (65500, 1), (65510, 2),
  10.       (120831, 1), (262141, 2), (1114109, 1),
  11.     ]
  12.     width = 0
  13.     for each in string:
  14.         if ord(each) == 0xe or ord(each) == 0xf:
  15.             each_width = 0
  16.             continue
  17.         elif ord(each) <= 1114109:
  18.             for num, wid in widths:
  19.                 if ord(each) <= num:
  20.                     each_width = wid
  21.                     width += each_width
  22.                     break
  23.             continue

  24.         else:
  25.             each_width = 1
  26.         width += each_width

  27.     return width
复制代码

2. 返回宽度对齐的字符串(需指定总宽度)
  1. def align_string(string, width):
  2.     string_width = get_str_width(string)
  3.     if width > string_width:
  4.         return string+' '*(width-string_width)
  5.     else:
  6.         return string
复制代码
  1. s1 = '一个长句子abcdef'
  2. s2 = '短句子123'
  3. print(align_string(s1, 20) + align_string(s2, 18))
  4. print(align_string(s2, 20) + align_string(s1, 18))
复制代码

结果:
  1. 一个长句子abcdef    短句子123
  2. 短句子123           一个长句子abcdef
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-7 16:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表