鱼C论坛

 找回密码
 立即注册
查看: 323|回复: 3

中文字符打印对齐

[复制链接]
发表于 2024-10-10 12:47:39 | 显示全部楼层 |阅读模式

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

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

x
大佬们求助,写了个tabular_printing()函数用于表格样式打印数据,但是含有中文的部分没法对齐,如下图所示:

                               
登录/注册后可看大图

  1. from faker import Faker
  2. from typing import List, Tuple

  3. def generate_data(faker):
  4.     return (
  5.         faker.name(),
  6.         faker.country(),
  7.         faker.phone_number(),
  8.         faker.ssn(),
  9.         faker.ascii_free_email(),
  10.         faker.date(),
  11.         faker.company()
  12.     )


  13. element = Tuple[str, str, str, str, str, str, str]
  14. fk1 = Faker(locale="en_US")
  15. fk2 = Faker(locale="zh_CN")
  16. data = [generate_data(faker=fk1) for _ in range(10)]
  17. data.insert(2, generate_data(faker=fk2))


  18. def tabular_printing(headers: Tuple, data: List) -> None:
  19.     table_rows = [headers]
  20.     table_rows.extend((str(i),) + row for i, row in enumerate(iterable=data, start=1))
  21.     column_widths = [max(len(str(item)) for item in col) for col in zip(*table_rows)]
  22.     separator = f"+{'+'.join('-' * (w + 2) for w in column_widths)}+"
  23.     sheet = [separator]
  24.     for row in table_rows:
  25.         sheet.append(f"|{'|'.join(f' {item:^{w}} ' for item, w in zip(row, column_widths))}|")
  26.         sheet.append(separator)
  27.     print(*sheet, sep="\n")


  28. if __name__ == '__main__':
  29.     headers = ("", "Name", "Country", "PhoneNumber", "IDCard", "E-mail", "Birthday", "Company")
  30.     tabular_printing(headers=headers, data=data)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-10 12:47:48 | 显示全部楼层
处理中文字符对齐问题时,主要是因为中英文字符的宽度不同。中文字符宽度通常比英文宽度大,导致用相同空格补齐时对齐出现问题。

可以通过以下方法解决此问题:

1. 使用 `str` 模块的 `str.width()` 方法获取字符的实际宽度。可使用如下函数来计算宽度:

  1. import unicodedata

  2. def get_display_width(s):
  3.     return sum(2 if unicodedata.east_asian_width(char) in 'FWA' else 1 for char in s)
复制代码


2. 修改 `tabular_printing()` 函数以支持宽度计算:

  1. def tabular_printing(headers: Tuple, data: List) -> None:
  2.     table_rows = []
  3.     table_rows.append(headers)
  4.     table_rows.extend((str(i),) + row for i, row in enumerate(iterable=data, start=1))
  5.    
  6.     # 计算列宽,考虑中文字符宽度
  7.     column_widths = [
  8.         max(get_display_width(str(item)) for item in column)
  9.         for column in zip(*table_rows)
  10.     ]
  11.    
  12.     separator = f"+{'+'.join('-' * (w + 2) for w in column_widths)}+"
  13.     sheet = []
  14.     sheet.append(separator)
  15.    
  16.     for row in table_rows:
  17.         formatted_row = "|".join(
  18.             f" {item}{' ' * (w - get_display_width(item))} " for item, w in zip(row, column_widths)
  19.         )
  20.         sheet.append(f"|{formatted_row}|")
  21.         sheet.append(separator)
  22.    
  23.     print(*sheet, sep="\n")
复制代码


这样调整后,函数应该可以处理中英文混合的情况,并实现表格对齐。确保在每个位置使用适当的空格量填充字符,从而实现美观的对齐效果。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-10 12:52:21 | 显示全部楼层
@FishC变化倒是有,但还是没有对齐

                               
登录/注册后可看大图
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-10 12:52:31 | 显示全部楼层
糖醋咸鱼微辣 发表于 2024-10-10 12:52
@FishC变化倒是有,但还是没有对齐https://s21.ax1x.c ...


看来您遇到了字符宽度计算的问题。中文字符在打印时通常比英文字符占用更多的空间。为了解决这个问题,我们可以使用 `unicodedata` 模块来判断字符宽度。这是一个处理字符宽度的简单示例:

  1. import unicodedata
  2. from typing import List, Tuple
  3. from faker import Faker

  4. def generate_data(faker):
  5.     return (
  6.         faker.name(),
  7.         faker.country(),
  8.         faker.phone_number(),
  9.         faker.ssn(),
  10.         faker.ascii_free_email(),
  11.         faker.date(),
  12.         faker.company()
  13.     )

  14. def get_display_width(s: str) -> int:
  15.     """Calculate width of string for display purpose, considering Chinese and full-width chars."""
  16.     return sum(2 if unicodedata.east_asian_width(char) in 'WF' else 1 for char in s)

  17. def tabular_printing(headers: Tuple, data: List) -> None:
  18.     # Add row numbers
  19.     table_rows = [headers] + [(str(i),) + row for i, row in enumerate(data, start=1)]
  20.    
  21.     # Determine the maximum width needed for each column
  22.     column_widths = [max(get_display_width(str(item)) for item in column) for column in zip(*table_rows)]
  23.    
  24.     # Print the separator
  25.     separator = f"+{'+'.join('-' * (w + 2) for w in column_widths)}+"
  26.     print(separator)

  27.     # Print each row of the table
  28.     for row in table_rows:
  29.         formatted_row = "|".join(
  30.             f" {item}{' ' * (w - get_display_width(item))} " for item, w in zip(row, column_widths)
  31.         )
  32.         print(f"|{formatted_row}|")
  33.         print(separator)

  34. if __name__ == '__main__':
  35.     headers = ("", "Name", "Country", "PhoneNumber", "IDCard", "E-mail", "Birthday", "Company")
  36.    
  37.     fk1 = Faker(locale="en_US")
  38.     fk2 = Faker(locale="zh_CN")
  39.     data = [
  40.         generate_data(faker=fk1),
  41.         generate_data(faker=fk2),
  42.         generate_data(faker=fk1)
  43.     ]
  44.    
  45.     tabular_printing(headers=headers, data=data)
复制代码


在 `get_display_width` 函数中,我们使用 `unicodedata.east_asian_width` 来判断字符是否为全宽字符(如中文字符),并将其宽度计算为 2,否则为 1。通过这种方式,您应该能够更好地对齐中英文字符混合的表格。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-19 22:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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