Home > Software engineering >  Best way to code custom loop to avoid str.format() key error in this example?
Best way to code custom loop to avoid str.format() key error in this example?

Time:10-23

I want to output something that looks like this (with 20 items per line):

\hyperlink{Psalm1}{1} & \hyperlink{Psalm2}{2} & \hyperlink{Psalm3}{3}  ...

Using Python (simplification of my loop, but enough to show the key error) I attempted:

        for indx in range(1, 150, 20):
            line = r""" \\hline
\\hyperlink{{{bn}{i}}}{{{i}}}  & \\hyperlink{{{bn}{i 1}}}{{{i 1}}} & \\hyperlink{{{bn}{i 2}}}{{{i 2}}} ... 
""".format( i=indx, bn = bookname)

What's the best way to recode to avoid the i 1 key error ?

CodePudding user response:

Try to use f string

for i in range(1, 150, 20):
  print(f"\\hyperlinkPPsalm{i} & \\hyperlinkPsalm{i 1} & \\hyperlinkPsalm{i 2}")

CodePudding user response:

Here is example of string generation (\hyperlink{Psalm1}{1}) using different methods:

i = 1
# string concatenation
formatted = r"\hyperlink{Psalm"   str(i)   "}{"   str(i)   "}"
# old-style formatting
formatted = r"\hyperlink{Psalm%d}{%d}" % (i, i))
# str.format
formatted = r"\hyperlink{{Psalm{0}}}{{{0}}}".format(i)
# f-string
formatted = rf"\hyperlink{{Psalm{i}}}{{{i}}}"

For this particular case I find old-style formatting more "clean" as it doesn't require doubling curly brackets.

To print 20 strings in each line you can pass generator which will produce formatted strings into str.join().

Full code:

stop = 150
step = 20
for i in range(1, stop   1, step):
    print(
        " & ".join(
            r"\hyperlink{Psalm%d}{%d}" % (n, n)
            for n in range(i, min(i   step, stop   1))
        )
    )

Or you can also use "one-liner":

stop = 150
step = 20
print(
    "\n".join(  # use " &\n".join(...) if you need trailing '&'
        " & ".join(
            r"\hyperlink{Psalm%d}{%d}" % (n, n)
            for n in range(i, min(i   step, stop   1))
        )
        for i in range(1, stop   1, step)
    )
)
  • Related