I am writing a four loop in my program that writes data to a file. I'm wanting for the output to be formatted as follows
frame001 + K.1
frame002 + K.2
...
frame099 + K.99
frame100 + K.100
So far I am doing
for f in range(1, 100):
file.write('frame' + str(f) + ' + K.' + str(f) + '\n')
I have no problem having the K part come out correctly as K.1-K.100, but I don't know how to have prefix zeros/have it output also frame00F to frameFFF with the appropriate amount of preceding zeros.
Using str.format:
>>> 'frame{0:03d} + K.{0}\n'.format(1)
'frame001 + K.1\n'
>>> 'frame{0:03d} + K.{0}\n'.format(100)
'frame100 + K.100\n'
BTW, range(1, 100) will not yield 100. If you want 100 to be included, that should be range(1, 101).
If you are using old version of Python (Python 2.5-), use % operator (String formatting operator) instead (need to specify multiple argument unlike str.format)
>>> 'frame%03d + K.%d\n' % (1, 1)
'frame001 + K.1\n'
>>> 'frame%03d + K.%d\n' % (100, 100)
'frame100 + K.100\n'
If you don't want to repeat arguments, you can pass mapping instead with slightly different format specifier:
>>> 'frame%(i)03d + K.%(i)d\n' % {'i': 1}
'frame001 + K.1\n'
Related
I want to output something that looks like this (with 20 items per line, and two variables are needed, one for indexing, i, and one for the book name, bookname, in this case "Psalm"):
\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 ?
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)
)
)
Try to use f string
for i in range(1, 150, 20):
print(f"\\hyperlinkPPsalm{i} & \\hyperlinkPsalm{i+1} & \\hyperlinkPsalm{i+2}")
I'm writing this code
for n in filtered_list:
for a in range(1,3):
duplicate = str(filenameRegex.group(1) + "(" + n + ")" + filenameRegex.group(2))
I've been wondering is there a more concise way to write this? I mean the "(" + n + ")" part. I was thinking about something like %s s = n, but I don't know and couldn't trial-and-error how to use it in this case.
In this case, you have to use %d instead of %s because n is an integer, not a string !
for n in filtered_list:
for a in range(1, 3):
duplicate = "%s(%d)%s" % (filenameRegex.group(1), n, filenameRegex.group(2))
This is old-school formatting, though. In Python 3 you can use f-strings:
for n in filtered_list:
for a in range(1, 3):
duplicate = f"{filenameRegex.group(1)}({n}){filenameRegex.group(2)}"
you can try like this:
duplicate = "%s(%s)%s"%(filenameRegex.group(1),n,filenameRegex.group(2))
or
duplicate = "{0}({1}){2}".format(filenameRegex.group(1),n,filenameRegex.group(2))
How can I treat numbers as symbols in SymPy?
For example, if I am performing a factorization with symbols I get:
from sympy import factor
factor('a*c*d + a*c*e + a*c*f + b*c*d + b*c*e + b*c*f')
c*(a + b)*(d + e + f)
I would like the same behaviour when I am using numbers in the expression.
Instead of
from sympy import factor
factor('2006*c*d + 2006*c*e + 2006*c*f + 2007*c*d + 2007*c*e + 2007*c*f')
4013*c*(d + e + f)
I would like to get
from sympy import factor
factor('2006*c*d + 2006*c*e + 2006*c*f + 2007*c*d + 2007*c*e + 2007*c*f')
c*(2006 + 2007)*(d + e + f)
Replace each constant with a unique symbol.
Factor the resulting expression.
Replace the unique symbols with the constants.
For your given case, something like this:
simple = factor('const2006*c*d + const2006*c*e + const2006*c*f + const2007*c*d + const2007*c*e + const2007*c*f')
simple.replace("const", '')
print(simple)
This should give you the desired output. You can identify numeric tokens in the expression with a straightforward regex or trivial parser -- either of which is covered in many other locations.
Symbol trickery to the rescue: replace your numbers with Symbols having a name given by the number. In your case you don't have to watch for negative versions so the following is straightforward:
>>> s = '2006*c*d + 2006*c*e + 2006*c*f + 2007*c*d + 2007*c*e + 2007*c*f'
>>> eq = S(s, evaluate=False); eq
2006*c*d + 2007*c*d + 2006*c*e + 2007*c*e + 2006*c*f + 2007*c*f
>>> reps = dict([(i,Symbol(str(i))) for i in _.atoms(Integer)]); reps
{2006: 2006, 2007: 2007}
>>> factor(eq.subs(reps))
c*(2006 + 2007)*(d + e + f)
Note: the evaluate=False is used to keep the like-terms from combining to give 4013*c*d + 4013*c*e + 4013*c*f.
I'm writing a code where I need to substitute variables of a function with multiple functions.
For example, I have B=x1**2+x2**2+x3**2 where I need to substitute x1=cos(x1+x2), x2=sin(x2+x3) and x3=x1 so as to get this value: cos(x1+x2)**2+sin(x2+x3)**2+x1**2
However, when I do this iteratively like this:
for j in range(nvar):
B=expand(B.subs(x[j],f[j]))
where nvar=3 and x is defined as a list of symbols and f as a list of symbolic functions, at each iteration, x[j] from the previous substitution is replaced and gives a wrong answer: x1**2 + sin(x1 + cos(x1 + sin(x1 + x2)))**2 + cos(x1 + sin(x1 + cos(x1 + sin(x1 + x2))))**2
How can I perform this substitution simultaneously?
You can use the simultaneous keyword for subs which was made for cases like this:
>>> (x1**2+x2**2+x3**2).subs(dict(x1=cos(x1+x2), x2=sin(x2+x3), x3=x1), simultaneous=True)
x1**2 + sin(x2 + x3)**2 + cos(x1 + x2)**2
Or, if x and f contain all instances of replacements you are interested in,
>>> reps = dict(zip(x, f))
>>> B = expand(B.subs(reps, simultaneous=True)
I have such a script;
for b in range(len(xy_alignments.keys())):
print str(b) + " : " + str(len(xy_alignments.keys()))
x = xy_alignments.keys()[b][0]
y = xy_alignments.keys()[b][1]
yx_prob = yx_alignments[(y,x)] / x_phrases[x]
xy_prob = xy_alignments[(x,y)] / y_phrases[y]
line_str = x + "\t" + y + "\t" + str(yx_prob) + "\t" + str(xy_prob) + "\n"
of.write(line_str.encode("utf-8"))
of.close()
xy_alignments, yx_alignments, x_phrases, and y_phrases are
python defaultdict variables which involve millions of keys.
When I run the loop above, it runs damn slowly.
Do python lovers have a suggestion to make it fast?
Thanks,
Here's a more idiomatic version, that should also be faster.
for (x, y), xy_alignment in xy_alignments.iteritems():
yx_prob = yx_alignments[(y, x)] / x_phrases[x]
xy_prob = xy_alignment / y_phrases[y]
of.write(b'%s\t%s\t%s\t%s\n' % (x, y, yx_prob, xy_prob))
This
saves the key() calls which create new lists every time,
saves one dict lookup by using iteritems(),
saves string allocations by using string formatting, and
saves the encode() call because all output is in the ascii range anyway.