subtraction operator python - python

I want to reduce the number of "the" words from a by 2. But this code doesn't seem to run. I cannot understand why the multiplication operator works but the subtraction operator doesn't.
b = "the"
a = b * 5
print a
a -= (b * 2)
print a
output
the
the the the the the
Traceback (most recent call last):
a -= (b * 2)
TypeError: unsupported operand type(s) for -=: 'str' and 'str'
How can I reduce the number of "the" 's in a by 2. If this cannot be done like this then is there a easier method perform this?

b = "the"
a = b * 5
print a
a = a[:-2*len(b)]
print a
# returns: thethethe
I am not substracting (you cannot really do it with strings), I am removing twice the length of b from the end of a, ignoring its real value.

To reduce the number of "the" by 2 in you word, try with the replace method :
b = "the"
a = b * 5
print a
>>> "thethethethethe"
a = a.replace(b, "", 2) # or a.replace(b*2, "", 1) if you want to remove "thethe" from the string
print a
>>> "thethethe"
If you wanted to remove the "the" by starting from the end, use rsplit()
b = "the"
a = "theAtheBthethe"
a = "".join(a.rsplit("the", 2)) # or "".join(a.rsplit("thethe", 1)) if you want to remove "theth" of the string
print a
>>> "theAtheB"
As described here, the * operator is supported by string (and unicode, list, tuple, bytearray, buffer, xrange types), b * 5 returns 5 copies of b concatenated.

Depends if you want to chop them off the start or the end, you can use array subsets:
>>> a[2*len("the"):]
'thethethe'
>>> a[:-(2*len("the"))]
'thethethe'

There is no support for subtraction operator in case of strings, but you can simply add one:
>>> class MyStr(str):
def __init__(self, val):
return str.__init__(self, val)
def __sub__(self, other):
if self.count(other) > 0:
return self.replace(other, '', 1)
else:
return self
and this will work in the following way:
>>> a = MyStr('thethethethethe')
>>> b = a - 'the'
>>> a
'thethethethethe'
>>> b
'thethethethe'
>>> b = a - 2 * 'the'
>>> b
'thethethe'
Regarding a - 2 * 'the' operation you should be aware that this is not " remove twice 'the' string from a ", but " remove result of (2 times 'the') from a " (first multiply "the" by 2 and then subtract from a).
Is this what you expected?

a = a.rpartition(b * 2)[0]
should do this, cutting from the right side. If you don't have any examples of 'thethe' in a, it will return the empty string ''. It won't work if you have multiple 'the's that are separated by other characters. For that, you could use a.rpartition(b)[0] twice. If you want to cut from the left instead, use a.partition(b * 2)[2].
Why doesn't subtracting work? Using addition and multiplication is a convenience feature for working with strings. The semantics of subtracting (or dividing) strs is not defined for Python, so you can't use it that way.

Plus operator work because "+" concatenate whilst minus don't operate on strings. You can try something using regular expression, like:
import re
s="the"*5
expr="the"
print s
# s -= 2
print "".join(re.findall(expr,s)[:-2])
# s -=3
print "".join(re.findall(expr,s)[:-3])

Related

How to convert infix to prefix if the operator present in front of expression?

if an equation is (- 3 + 5), how could I convert it into prefix?
It's operator is in front of the equation.
If you print the unevaluate expression with srepr it will show exactly how the expression is represented in SymPy/Python:
>>> from sympy import srepr, Add
>>> srepr(Add(-3,5,evaluate=False))
'Add(Integer(-3), Integer(5))'
I'm guessing you don't want this. The most general way of handling printing is to create a custom printer (and you would have to check the documentation on that). Alternatively, depending on how complicated of a case you want to deal with, you could handle a simple case like this:
>>> from sympy import Add, Mul, S, Symbol
>>> ops = {Add: '+(%s, %s)', Mul: '*(%s, %s)'}
>>> def pr(eq):
... eq = S(eq)
... if eq.func not in ops: return str(eq)
... a, b = eq.as_two_terms()
... return ops[eq.func] % (pr(a), pr(b))
>>> pr(x + y)
'+(x, y)'
>>> pr(3*x + y - z)
'+(y, +(*(-1, z), *(3, x)))'
There's an alternative to working with literal numbers so they will behave like symbols: create symbols with names being the strings of the numbers, e.g.
>>> a, b = (-3, 5)
>>> pr(a + b) # -3 + 5 collapses automatically to 2
'2'
>>> a, b = [Symbol(str(i)) for i in (a,b)] # create symbols from numbers
>>> pr(a + b)
'+(-3, 5)'

Append to string up to given value [duplicate]

I should define a function pad_with_n_chars(s, n, c) that takes a
string 's', an integer 'n', and a character 'c' and returns
a string consisting of 's' padded with 'c' to create a
string with a centered 's' of length 'n'. For example,
pad_with_n_chars(”dog”, 5, ”x”) should return the
string "xdogx".
With Python2.6 or better, there's no need to define your own function; the string format method can do all this for you:
In [18]: '{s:{c}^{n}}'.format(s='dog',n=5,c='x')
Out[18]: 'xdogx'
Using f-string: f'{"dog":x^5}'
yeah just use ljust or rjust to left-justify (pad right) and right-justify (pad left) with any given character.
For example ... to make '111' a 5 digit string padded with 'x'es
In Python3.6:
>>> '111'.ljust(5, 'x')
111xx
>>> '111'.rjust(5, 'x')
xx111
It looks like you're only looking for pointers, not a complete solution. So here's one:
You can multiply strings in python:
>>> "A" * 4
'AAAA'
Additionally I would use better names, instead of s I'd use text, which is much clearer. Even if your current professor (I suppose you're learning Python in university.) uses such horrible abbreviations.
In Python 3.x there are string methods: ljust, rjust and center.
I created a function:
def header(txt: str, width=45, filler='-', align='c'):
assert align in 'lcr'
return {'l': txt.ljust, 'c': txt.center, 'r': txt.rjust}[align](width, filler)
print(header("Hello World"))
print(header("Hello World", align='l'))
print(header("Hello World", align='r'))
Output:
-----------------Hello World-----------------
Hello World----------------------------------
----------------------------------Hello World
well, since this is a homework question, you probably won't understand what's going on if you use the "batteries" that are included.
def pad_with_n_chars(s, n, c):
r=n - len(s)
if r%2==0:
pad=r/2*c
return pad + s + pad
else:
print "what to do if odd ? "
#return 1
print pad_with_n_chars("doggy",9,"y")
Alternatively, when you are not schooling anymore.
>>> "dog".center(5,"x")
'xdogx'
print '=' * 60
header = lambda x: '%s%s%s' % ('=' * (abs(int(len(x)) - 60) / 2 ),x,'=' * (abs(int(len(x)) - 60) / 2 ) )
print header("Bayors")

Pad each element of the list with the following 0s

I have a list of lists:
0 [[[20.5973832, 52.8685205], [20.5974081, 52.86...
1 [[[21.0072715, 52.2413049], [21.0072603, 52.24...
2 [[[18.8446673, 50.4508418], [18.8447041, 50.45...
3 [[[18.8649393, 50.4483321], [18.8649802, 50.44...
4 [[[16.7529018, 53.1424612], [16.7528965, 53..
I need to iterate over each element (each coordinate number) of the list, and make sure it has 7 digits after the period. If it doesn't, I need to pad it with a 0 at the end to make it to have 7 digits after the period.
Each number is a float, but I can convert it to string to use the len() function.
The code I have is:
for a in list_of_lists:
for b in a:
for c in b:
for d in c:
if(len(str(d))<10):
d = str(d).ljust(10-len(str(d)), '0')
The error I am getting is:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-46-70d9d844f41b> in <module>
3 for a in list_of_lists:
4 for b in a:
----> 5 for c in b:
6 for d in c:
7 if(len(str(d))<10):
TypeError: 'float' object is not iterable
What is the better way of achieving this?
recursive_tran is a recursive helper function to access every value in your list of list of whatever with possibility to replace or modify value.
(credit: Python: Replace values in nested dictionary)
Solution
3 Options I can see (you can run them by changing method parameter):
Custom Repr
It will not change anything at all, we just create new float class and override repr function with string formatter. This one is really nice as it formats without string apostrophes and value itself is not changed at all. I suggest this solution
String Substitution
Its pretty much the same like 1), but the difference is that we replace real float with formatted string, so you lose value, but you have what you wanted. Another downside is that the string has apostrophes
Rounding
The real deal, but not as nice as you want. It rounds the number up to 7 decimals, but the issue is, that if you have some number like 5.0, it will not give you all decimals you wants (5.0000000) as there is not really point to it.
See below for results
def recursive_tran(l: list, depth: int = 0, method: str = "round") -> list:
x = []
for e in l:
if isinstance(e, list):
e = recursive_tran(e, depth=depth + 1, method=method)
if isinstance(e, float) or isinstance(e, int):
if method == "round":
e = round(e, 7)
if method == "format":
e = format(e, ".7f")
if method == "custom_repr":
e = FakeRepresentationFloat(round(e, 7))
x.append(e)
return x
class FakeRepresentationFloat(float):
def __repr__(self):
return format(self, ".7f")
x = [[[1.0158, 5.7000155587, [[1, 2.000000000000000008]]]]]
print("Custom repr")
print(recursive_tran(x, method="custom_repr"))
print("String substitution")
print(recursive_tran(x, method="format"))
print("Rounding")
print(recursive_tran(x, method="round"))
>>> Custom repr
>>> [[[1.0158000, 5.7000156, [[1.0000000, 2.0000000]]]]]
>>> String substitution
>>> [[['1.0158000', '5.7000156', [['1.0000000', '2.0000000']]]]]
>>> Rounding
>>> [[[1.0158, 5.7000156, [[1, 2.0]]]]]

In python, test for 1 or 3 consecutive instances of a string, but not 2 (without regex)

I am dealing with data in which...
* marks property A
** marks property B
*** marks properties A & B
text1 = "spam*eggs" # A
text2 = "eggs**spam" # B
text3 = "spam***spam" # A & B
Testing for property B is easy,
"**" in <string>
but testing for property A with the same strategy would give a false positive with text2.
>>> "*" in text2
True
I want to test for property A. Is there a pythonic way to do this without using regular expressions? I don't want to use regex because I share code with beginner programmers who are not familiar with it.
Try this:
idx = txt.index('*')
if txt[idx+1] != '*':
print 'A'
elif txt[idx+2] != '*':
print 'B'
else:
print 'A & B'
The above will raise exceptions for the corner cases - for example, if the string is not present, or if the string is the last character. This solution has the added benefit of performing a single traversal of the text (the call to index()).
Without Regex, you could do something like this:
if "***" in mystr:
print "Property A & B"
elif "**" in mystr:
print "Property B"
elif "*" in mystr:
print "Property A"
You can count the occurrences of '*':
>>> text1.count('*')
1
>>> text2.count('*')
2
>>> text3.count('*')
3
So your check would be text.count('*') in (1, 3)
That said, I agree with the commenter - regular expressions are right for this kind of problem.
>>> properties = {1: 'A', 2: 'B', 3: 'A & B'}
>>> import re
>>> text = 'eggs***spam'
>>> match = re.search(r'\*+', text)
>>> if match:
... print properties[len(match.group(0))]
... else:
... print 'None'
A & B
Well, I wouldn't say it's Pythonic, but you could group them and make sure the consecutive occurrences are of a certain length - either 1 or 3 to exclude ** for instance, eg:
from itertools import groupby
print any(k=='*' and len(list(g)) in (1, 3) for k, g in groupby(s))
It is not clear if you want to just test for Property A, as in the text, or A or C, as in the title. (C being A and B)
To just get True or False for 1 or 3 and not 2, you can use a code rephrasing of your logic:
result = '***' in x or (not '**' in x and '*' in x)
To get the letter of ABC out depending on the pattern:
result = ['None','A','B','C'][('*' in x) + ('**' in x) + ('***' in x)]
To just test for Property A (one star) without failing on two or three. (EDIT: simplified this. If ** is not there then neither is ***):
isItA = '*' in x and not '**' in x

What does it mean += in Python?

What does it mean when it's like this:
self.something += ('somethin',)
What does "+=" mean and what does the comma mean?
The expression a += b is shorthand for a = a + b, where a and b can be numbers, or strings, or tuples, or lists (but both must be of the same type).
The comma in ('x',) means that this is a tuple of a single element, 'x' . If the comma is absent, is just an 'x' between parenthesis.
+= is addition and assignment into one (sometimes referred to as iadd or in-place add). It is the same as a = a + x
a = 4
a += 5 # add 5 to a, and assign the result into a
b = 4
b = b + 5 # this does the same thing as +=
print a # prints out 9
print b # prints out 9
You can also do other operations in this style, such as -=, *=, /=, &= (bitwise and), |= (bitwise or), ^= (bitwise xor), %= (mod), **= (exponent).
('something',) is a tuple. ('something') (without the comma) is using the parenthesis in grouping, kind of like ('some' + 'thing') or (a + b). In order to differentiate between the one-member tuple and the grouping syntactically, Python uses a comma.
Python has an operator to assign value to a name and it's =.
The language also support many other operators like +, -, ** for operations defined in special methods of your objects.
Although + is the math sign to add things, it can be customized to do whatever you want.
Sometimes you want to make an operation and store it using the same name. For these situations you have in-place operators that are just the normal operators you're use to plus the = sign.
For immutable objects (numbers, strings, tuples,...) you can't have in-place changes because... they're immutable. So, the in-place methods do exactly the same thing the normal method followed by an assignment.
For mutable objects the difference is much clear:
In-place add:
>>> a = []
>>> b = a
>>> b += [1,2]
>>> a
[1, 2]
Add and assign:
>>> a = []
>>> b = a
>>> b = b + [1,2]
>>> a
[]
See? The object itself was transformed with the in-place add for lists, but, on the other case, a new object was created.
For your other question, the comma is the tuple separator.
a = (1) # Just number 1 inside parenthesis
a = (1,) # A tuple with one element
results=[]
for x in range(5):
results += '$'
print(results)
output : ['$', '$', '$', '$', '$']
this code behaves differently from typical += operator , as you can see here it has generated list with $ sign inside it.
its is not like we think results = results+ '$' this code will throw you an error.
What actually happens is += operator works like .extend() in lists.

Categories