Python 两个文本并排,宽度精确
Python two text side by side with precise width
我有一个练习,其中有两个文本,“左”和“右”。
我需要创建一个函数,在给定宽度作为参数的情况下将它们并排放置,所有这些都使用 itertools 和 textwrap。
这是我的代码:
import textwrap
import itertools
def sidebyside(left,right,width=79):
width = round((width+1)/2)
leftwrapped = textwrap.wrap(left,width = width-1)
for i in range(0,len(leftwrapped)):
leftwrapped[i] = leftwrapped[i].ljust(width)
rightwrapped = textwrap.wrap(right,width = width-1)
for i in range(0,len(rightwrapped)):
rightwrapped[i] = rightwrapped[i].ljust(width)
pipes = ["|"]*max(len(leftwrapped),len(rightwrapped))
paragraph = itertools.zip_longest(leftwrapped,pipes,rightwrapped, fillvalue="".ljust(width))
result = ""
for a in paragraph:
result = result + a[0] + a[1] + a[2] + "\n"
return(result)
这是“左”和“右”的示例:
left = (
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
"Sed non risus. "
"Suspendisse lectus tortor, dignissim sit amet, "
"adipiscing nec, utilisez sed sin dolor."
)
right = (
"Morbi venenatis, felis nec pretium euismod, "
"est mauris finibus risus, consectetur laoreet "
"sem enim sed arcu. Maecenas sit amet eleifend sem. "
"Nullam ac libero metus. Praesent ac finibus nulla, vitae molestie dolor."
" Aliquam vestibulum viverra nisl, id porta mi viverra hendrerit."
" Ut et porta augue, et convallis ante."
)
我的问题是我遇到了一些间距问题,即:对于第一行,对于给定长度 20,我有以下输出:
'Lorem |Morbi ven '
但我需要这个输出:
'Lorem |Morbi ven'
找到了,我的round函数不好,只好做两个width,第一个是除法的round,第二个是width - round(width/2)
的结果。
谈话很便宜,代码更好:
从 itertools 导入 zip_longest
导入文字环绕
def sidebyside(left, right, width=79):
mid_width = (width - (1 - width%2)) // 2
return "\n".join(
f"{l.ljust(mid_width)}|{r.ljust(mid_width)}"
for l, r in zip_longest(
*map(lambda t: textwrap.wrap("".join(t), mid_width), (left, right)),
fillvalue=""
)
)
最初的 post 的目标是解决一个编程难题,该难题需要仅使用 itertools.zip_longest()
和 textwrap.wrap()
来实现 sidebyside()
方法。
此方法有效但有一些缺点。例如,它不支持 left
和 right
文本中的换行符(在文本重排为 side-by-side 之前删除所有间距)。
因为这是一个非常有用的方法,所以我写了一个改进版本,see the Gist itself for more information。
例如:
# some random text
LOREM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
# split into paragraphs
LOREM_PARA = LOREM.replace(". ", ".\n\n").split("\n")
# arbitrarily truncate the first two lines for text B
TEXT_A = LOREM_PARA[:]
TEXT_B = LOREM_PARA[2:]
# reflow as side-by-side
print(side_by_side(TEXT_A, TEXT_B, width=50, as_string=True))
将输出:
Lorem ipsum dolor sit | Ut enim ad minim
amet, consectetur | veniam, quis nostrud
adipiscing elit, sed do | exercitation ullamco
eiusmod tempor | laboris nisi ut aliquip
incididunt ut labore et | ex ea commodo
dolore magna aliqua. | consequat.
|
Ut enim ad minim | Duis aute irure dolor
veniam, quis nostrud | in reprehenderit in
exercitation ullamco | voluptate velit esse
laboris nisi ut aliquip | cillum dolore eu fugiat
ex ea commodo | nulla pariatur.
consequat. |
| Excepteur sint occaecat
Duis aute irure dolor | cupidatat non proident,
in reprehenderit in | sunt in culpa qui
voluptate velit esse | officia deserunt mollit
cillum dolore eu fugiat | anim id est laborum.
nulla pariatur. |
|
Excepteur sint occaecat |
cupidatat non proident, |
sunt in culpa qui |
officia deserunt mollit |
anim id est laborum. |
我有一个练习,其中有两个文本,“左”和“右”。
我需要创建一个函数,在给定宽度作为参数的情况下将它们并排放置,所有这些都使用 itertools 和 textwrap。
这是我的代码:
import textwrap
import itertools
def sidebyside(left,right,width=79):
width = round((width+1)/2)
leftwrapped = textwrap.wrap(left,width = width-1)
for i in range(0,len(leftwrapped)):
leftwrapped[i] = leftwrapped[i].ljust(width)
rightwrapped = textwrap.wrap(right,width = width-1)
for i in range(0,len(rightwrapped)):
rightwrapped[i] = rightwrapped[i].ljust(width)
pipes = ["|"]*max(len(leftwrapped),len(rightwrapped))
paragraph = itertools.zip_longest(leftwrapped,pipes,rightwrapped, fillvalue="".ljust(width))
result = ""
for a in paragraph:
result = result + a[0] + a[1] + a[2] + "\n"
return(result)
这是“左”和“右”的示例:
left = (
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
"Sed non risus. "
"Suspendisse lectus tortor, dignissim sit amet, "
"adipiscing nec, utilisez sed sin dolor."
)
right = (
"Morbi venenatis, felis nec pretium euismod, "
"est mauris finibus risus, consectetur laoreet "
"sem enim sed arcu. Maecenas sit amet eleifend sem. "
"Nullam ac libero metus. Praesent ac finibus nulla, vitae molestie dolor."
" Aliquam vestibulum viverra nisl, id porta mi viverra hendrerit."
" Ut et porta augue, et convallis ante."
)
我的问题是我遇到了一些间距问题,即:对于第一行,对于给定长度 20,我有以下输出:
'Lorem |Morbi ven '
但我需要这个输出:
'Lorem |Morbi ven'
找到了,我的round函数不好,只好做两个width,第一个是除法的round,第二个是width - round(width/2)
的结果。
谈话很便宜,代码更好:
从 itertools 导入 zip_longest
导入文字环绕
def sidebyside(left, right, width=79):
mid_width = (width - (1 - width%2)) // 2
return "\n".join(
f"{l.ljust(mid_width)}|{r.ljust(mid_width)}"
for l, r in zip_longest(
*map(lambda t: textwrap.wrap("".join(t), mid_width), (left, right)),
fillvalue=""
)
)
最初的 post 的目标是解决一个编程难题,该难题需要仅使用 itertools.zip_longest()
和 textwrap.wrap()
来实现 sidebyside()
方法。
此方法有效但有一些缺点。例如,它不支持 left
和 right
文本中的换行符(在文本重排为 side-by-side 之前删除所有间距)。
因为这是一个非常有用的方法,所以我写了一个改进版本,see the Gist itself for more information。
例如:
# some random text
LOREM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
# split into paragraphs
LOREM_PARA = LOREM.replace(". ", ".\n\n").split("\n")
# arbitrarily truncate the first two lines for text B
TEXT_A = LOREM_PARA[:]
TEXT_B = LOREM_PARA[2:]
# reflow as side-by-side
print(side_by_side(TEXT_A, TEXT_B, width=50, as_string=True))
将输出:
Lorem ipsum dolor sit | Ut enim ad minim
amet, consectetur | veniam, quis nostrud
adipiscing elit, sed do | exercitation ullamco
eiusmod tempor | laboris nisi ut aliquip
incididunt ut labore et | ex ea commodo
dolore magna aliqua. | consequat.
|
Ut enim ad minim | Duis aute irure dolor
veniam, quis nostrud | in reprehenderit in
exercitation ullamco | voluptate velit esse
laboris nisi ut aliquip | cillum dolore eu fugiat
ex ea commodo | nulla pariatur.
consequat. |
| Excepteur sint occaecat
Duis aute irure dolor | cupidatat non proident,
in reprehenderit in | sunt in culpa qui
voluptate velit esse | officia deserunt mollit
cillum dolore eu fugiat | anim id est laborum.
nulla pariatur. |
|
Excepteur sint occaecat |
cupidatat non proident, |
sunt in culpa qui |
officia deserunt mollit |
anim id est laborum. |