I want to know how can is shorten this code and make it look more proper - python-3.x

I want to know if the code I wrote can be shortened further, I was practicing and I came up to a task which asks you to return a boolean value, this is what the question says:
Given two strings, return True if either of the strings appears at the
very end of the other string, ignoring upper/lower case differences
(in other words, the computation should not be "case sensitive").
Note: s.lower() returns the lowercase version of a string.
def end_other(a, b):
x = len(b)
n = a[-x:]
y = len(a)
m = b[-y:]
if b.lower() == n.lower() or a.lower() == m.lower() :
return True
else:
return False
The Code is working properly but I wondered if it can be shortened more so it looks good.

You can write it like this:
def end_other(a, b):
n = a[-len(b):]
m = b[-len(a):]
return b.lower() == n.lower() or a.lower == m.lower()
I removed variables x and y because they are used just one time and then I also remove the if-else statement because it's unnecessary, in fact you can just return the result of the comparison instead of checking it's result and returning it a second time.

Related

Finding a substring in a jumbled string

I am writing a script - includes(word1, word2) - that takes two strings as arguments, and finds if word1 is included in word2. Word2 is a letter jumble. It should return Boolean. Also repetition of letters are allowed, I am only checking if the letters are included in the both words in the same order.
>>>includes('queen', 'qwertyuytresdftyuiokn')
True
'queen', 'QwertyUytrEsdftyuiokN'
I tried turning each word into lists so that it is easier to work with each element. My code is this:
def includes(w1, w2):
w1 = list(w1)
w2 = list(w2)
result = False
for i in w1:
if i in w2:
result = True
else:
result = False
return result
But the problem is that I need to also check if the letters of word1 comes in the same order in word2, and my code doesn't controls that. I couldn't find a way to implement that with list. Just like I couldn't do this much with strings, so I think I need to use another data structure like dictionary but I don't know much about them.
I hope I understood what is your goal.
Python is not my thing, but I think I made it pythonic:
def is_subsequence(pattern, items_to_use):
items_to_use = (x for x in items_to_use)
return all(any(x == y for y in items_to_use) for x, _ in itertools.groupby(pattern))
https://ideone.com/Saz984
Explanation:
itertools.groupby transfers pattern in such way that constitutive duplicates are discarded
all items form form grouped pattern must fulfill conditions
any uses generator items_to_use as long as it doesn't matches current item. Note that items_to_use mus be defined outside of final expression so progress on it is kept every time next item from pattern is verified.
If you are not just checking substrings:
def include(a, b):
a = "".join(set(a)) # removes duplicates
if len(a) == 1:
if a in b:
return True
else:
return False
else:
try:
pos = b.index(a[0])
return include(a[1:], b[pos:])
except:
return False
print(include('queen', 'qwertyuytresdftyuiokn'))
#True

Mark Element in List

I have an excercise about prime numbers that requires me to write a function which takes a list of elements and a number p and marks elements False which are in the range 2p, 3p...N
First I create a list of True and False:
true_value = [False, False] + [True for x in range(n-1)] #Let assumme that n=16
And then I write the function that find the even number in this list (with p = 2)
def mark_false(bool_list, p):
range_new = [x for x in range(len(bool_list))]
for i in range(2, len(range_new)):
for j in range(p, len(range_new), p):
if (i*p == range_new[j]) & (i*p <= len(range_new)):
bool_list[j] = False
return bool_list
This function help me to find the location of the even number (>2) and return to False
Example: a = list_true(16)
a = [False,False,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True]
b = mark_false(a, 2)
b = [False,False,True,True,False,True,False,True,False,True,False,True,False,True,False,True]
This function mark_false does work but the problem is everytime I run it I have to create a list range_new which takes a lot of time to calculate. So how do I rewrite this function so it can run faster without creating new lists?
You seem to be doing things the long way around, searching for the j value that matches the multiple of p you want to set to False. But since you already know that value already, there's no need to search for it, just set it directly.
I'd do:
def mark_false(bool_list, p):
for i in range(p, len(bool_list), p): # p, 2*p, 3*p, ...
bool_list[i] = False # do the assignment unconditionally
You probably shouldn't need a return statement, since you're modifying the list you are passed in-place. Returning the list could make the API misleading, as it might suggest that the returned list is a new one (e.g. a modified copy).
If you did want to return a new list, you could create one with a list comprehension, rather than modifying the existing list:
def mark_false_copy(bool_list, p):
return [x if i % p else False for i, x in enumerate(bool_list)]

how to add characters from array into one string python

I'm trying to change characters from x into upper or lower character depending whether they are in r or c. And the problem is that i can't get all the changed characters into one string.
import unittest
def fun_exercise_6(x):
y = []
r = 'abcdefghijkl'
c = 'mnopqrstuvwxz'
for i in range(len(x)):
if(x[i] in r):
y += x[i].lower()
elif(x[i] in c):
y += x[i].upper()
return y
class TestAssignment1(unittest.TestCase):
def test1_exercise_6(self):
self.assertTrue(fun_exercise_6("osso") == "OSSO")
def test2_exercise_6(self):
self.assertTrue(fun_exercise_6("goat") == "gOaT")
def test3_exercise_6(self):
self.assertTrue(fun_exercise_6("bag") == "bag")
def test4_exercise_6(self):
self.assertTrue(fun_exercise_6("boat") == "bOaT" )
if __name__ == '__main__':
unittest.main()
Using a list as you are using is probably the best approach while you are figuring out whether or not each character should be uppered or lowered. You can join your list using str's join method. In your case, you could have your return statement look like this:
return ''.join(y)
What this would do is join a collection of strings (your individual characters into one new string using the string you join on ('').
For example, ''.join(['a', 'b', 'c']) will turn into 'abc'
This is a much better solution than making y a string as strings are immutable data types. If you make y a string when you are constructing it, you would have to redefine and reallocate the ENTIRE string each time you appended a character. Using a list, as you are doing, and joining it at the end would allow you to accumulate the characters and then join them all at once, which is comparatively very efficient.
If you define y as an empty string y = "" instead of an empty list you will get y as one string. Since when you declare y = [] and add an item to the list, you add a string to a list of string not a character to a string.
You can't compare a list and a string.
"abc" == ["a", "b", "c'] # False
The initial value of y in the fun_exercise_6 function must be ""

Why can't input() in Python 3.6 be placed in an if _ is _: statement like this one?

Edited version
x = input("Put 'thing' here \n")
if x is 'thing':
print("Success thingx!")
else:
print(x)
y = "thing"
if y is 'thing':
print("Success thingy!")
else:
print(x)
While I expected my result to be
Put 'thing' here
thing
#above is the input
Success thingx!
Success thingy!
I got the result
Put 'thing' here
thing
#above is the input
thing
Success thingy!
Is there an error in how I am writing this?
the is operator checks for identity. cpython use string interning to use the same str objects in different places. But, when using the input method a new str object is created and not the interned one
is => id(x1) == id(x2)
adding some id prints
x = str(input("Put 'thing' here \n"))
print('x', id(x))
print('thing', id('thing'))
if x is 'thing':
print("Success thingx!")
else:
print(x)
y = str("thing")
print('y', id(y))
if y is 'thing':
print("Success thingy!")
else:
print(x)
then the output is
thing
x 42666048
thing 42737760
thing
y 42737760
Success thingy!
you should use == if you want to test for equality
you're confusing is with ==
The is operator checks exact identity, that the two objects are actually the same exact object. This is implementation-specific and often the case for interned strings (small string literals) in cpython. The return value of input() is dynamically constructed and doesn't participate in interning here.
You want to use == to check equality between strings. Reserve is for singletons such as True, False, None, ... (Ellipsis), NotImplemented, types, etc.

Creating a function that returns index of minimum value in a list?

def minimum_index(xs):
minimum_index=xs[0]
for i in range(len(xs)):
if xs[i]<xs[i+1]:
min_i=i
elif xs[i]>xs[i+1]:
min_i=i+1
continue
return minimum_index
This looks correct to me, but for some reason, I keep trying to change things around and I either get an incorrect return value or no return value.
Simplify the function
def minimum_index(xs):
ans = 0
for i in range(1, len(xs)):
if xs[i] < xs[ans]:
ans = i
return ans
or in a more pythonic way
minimum_index = lambda xs: xs.index(min(xs))
Your code has at least two issues: You seem to have two variables that stand for the minimal index, and you mix them up. Also, it is not enough to compare subsequent elements, you will have to compare to the minimal value. Try this:
def minimum_index(xs):
minx = xs[0]
mini = 0
for i in range(1,len(xs)):
if xs[i]<minx:
mini = i
minx = xs[i]
return mini
If you are using numpy, then you can simply use their numpy.argmin(xs).

Resources