鱼C论坛

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

中文字符打印对齐

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

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

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

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

                               
登录/注册后可看大图
from faker import Faker
from typing import List, Tuple

def generate_data(faker):
    return (
        faker.name(),
        faker.country(),
        faker.phone_number(),
        faker.ssn(),
        faker.ascii_free_email(),
        faker.date(),
        faker.company()
    )


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


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


if __name__ == '__main__':
    headers = ("", "Name", "Country", "PhoneNumber", "IDCard", "E-mail", "Birthday", "Company")
    tabular_printing(headers=headers, data=data)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

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

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

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

2. 修改 `tabular_printing()` 函数以支持宽度计算:
def tabular_printing(headers: Tuple, data: List) -> None:
    table_rows = []
    table_rows.append(headers)
    table_rows.extend((str(i),) + row for i, row in enumerate(iterable=data, start=1))
    
    # 计算列宽,考虑中文字符宽度
    column_widths = [
        max(get_display_width(str(item)) for item in column)
        for column in zip(*table_rows)
    ]
    
    separator = f"+{'+'.join('-' * (w + 2) for w in column_widths)}+"
    sheet = []
    sheet.append(separator)
    
    for row in table_rows:
        formatted_row = "|".join(
            f" {item}{' ' * (w - get_display_width(item))} " for item, w in zip(row, column_widths)
        )
        sheet.append(f"|{formatted_row}|")
        sheet.append(separator)
    
    print(*sheet, sep="\n")

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

                               
登录/注册后可看大图
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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


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

def generate_data(faker):
    return (
        faker.name(),
        faker.country(),
        faker.phone_number(),
        faker.ssn(),
        faker.ascii_free_email(),
        faker.date(),
        faker.company()
    )

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

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

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

if __name__ == '__main__':
    headers = ("", "Name", "Country", "PhoneNumber", "IDCard", "E-mail", "Birthday", "Company")
    
    fk1 = Faker(locale="en_US")
    fk2 = Faker(locale="zh_CN")
    data = [
        generate_data(faker=fk1),
        generate_data(faker=fk2),
        generate_data(faker=fk1)
    ]
    
    tabular_printing(headers=headers, data=data)

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-16 06:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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