Checking elements of a list Python - python

places=["Jack", "John", "Sochi"]
place = places[0]
while places != "Sochi" and count < len(places):
if ' ' in place:
multi_word += 1
count += 1
place = places[count]
I basically want the program to check how many cities till Sochi, by adding one for each element of the list. Then when it reaches Sochi it stops adding 1 to the list then it do nothing when it reaches Sochi. The program adds one for every element of the list. Then it checks if their is a space in any of the elements of the list and if so adds one but only if that element of the list comes from Sochi. What is wrong with this program?
Also what does this line do..{count < len(places)}

The main error I see is that you need to check if place != "Sochi", instead of using places. Assuming you initialize count=0, this will give you the output you desire:
places = ["Jack", "John", "Sochi"]
place = places[count]
while place != "Sochi" and count < len(places):
if ' ' in place:
multi_word += 1
count += 1
place = places[count]
print 'Number of cities before Sochi:', count
The clause count < len(places) makes sure that you don't try access indices in places beyond the length of the list, which would return an IndexError.

places = ["Jack", "John", "Sochi"]
count=0
multi_word=0
place = places[count]
while place != "Sochi" and count < len(places):
if ' ' in place:
multi_word += 1
count += 1
place = places[count]
print ('Number of cities before Sochi:', count)
Here is the fixed code

Related

comma after every element in list instead of the last one

I want to make a function which would add comma after every word in list instead of the last one. I tried to do it with a while-loop so it could stop before the comma reaches the last word, but the output of the code is not doing its job.
list = ['Sadzo', 'Nimadaro', 'Duol']
wordIndex = 0
LenghtUnderIndex = len(list[wordIndex])
while wordIndex <= len(list):
list.insert(LenghtUnderIndex, ', ')
wordIndex += 1
break
print (*list)
This is what join is for.
out = ','.join(list)
However, do not name your variable list. That hides the Python type by the same name.
Why not just use:
for x in range(len(list) - 1):
list[x] = list[x] + ","

How to increment a list in python containing both numbers and characters?

I have a list as [1,2,3,a,b,M] and need to increment every variable by 1 .
I have tried for number I can use as :
a = [1,2,3]
for i in range(len(a)):
a[i] += 1
print a
Also for characters I can use :
ch = 'M'
x = chr(ord(ch) + 1)
print ("The incremented character value is : ")
print (x)
But together I am not able to club it. Is there anyway by which i can club it?
You could try a list comprehension
[e+1 if isinstance(e,int) else chr(ord(e) + 1) for e in [1,2,3,'a','b','M']]

How do I go about ending this loop?

I am trying to count the longest length of string in alphabetical order
s = 'abcv'
longest = 1
current = 1
for i in range (len(s) - 1):
if s[i] <= s[i+1]:
current += 1
else:
if current > longest:
longest = current
current = 0
i += 1
print longest
For this specific string, 'Current' ends up at the correct length, 4, but never modifies longest.
EDIT: The following code now runs into an error
s = 'abcv'
current = 1
biggest = 0
for i in range(len(s) - 1):
while s[i] <= s[i+1]:
current += 1
i += 1
if current > biggest:
biggest = current
current = 0
print biggest
It seems my logic is correct , but I run into errors for certain strings. :(
Although code sources are available on the internet which print the longest string, I can't seem to find how to print the longest length.
break will jump behind the loop (to sam indentation as the for statement. continue will jump to start of loop and do the next iteration
Your logic in the else: statement does not work - you need to indent it one less.
if s[i] <= s[i+1]:
checks for "is actual char less or equal then next char" - if this is the case you need to increment your internal counter and set longest if it is longer
You might get into trouble with if s[i] <= s[i+1]: - you are doing it till len(s)-1. "jfjfjf" is len("jfjfjf") = 6 - you would iterate from 0 to 5 - but the if accesses s[5] and s[6] which is more then there are items.
A different approach without going over explicit indexes and split into two responsibilities (get list of alphabetical substring, order them longest first):
# split string into list of substrings that internally are alphabetically ordered (<=)
def getAlphabeticalSplits(s):
result = []
temp = ""
for c in s: # just use all characters in s
# if temp is empty or the last char in it is less/euqal to current char
if temp == "" or temp[-1] <= c:
temp += c # append it to the temp substring
else:
result.append(temp) # else add it to the list of substrings
temp = "" # and clear tem
# done with all chars, return list of substrings
return result
# return the splitted list as copy after sorting reverse by length
def SortAlphSplits(sp, rev = True):
return sorted(sp, key=lambda x: len(x), reverse=rev)
splitter = getAlphabeticalSplits("akdsfabcdemfjklmnopqrjdhsgt")
print(splitter)
sortedSplitter = SortAlphSplits(splitter)
print (sortedSplitter)
print(len(sortedSplitter[0]))
Output:
['ak', 's', 'abcdem', 'jklmnopqr', 'dhs']
['jklmnopqr', 'abcdem', 'dhs', 'ak', 's']
9
This one returns the array of splits + sorts them by length descending. In a critical environment this costs more memory then yours as you only cache some numbers whereas the other approach fills lists and copies it into a sorted one.
To solve your codes index problem change your logic slightly:
Start at the second character and test if the one before is less that this. That way you will ever check this char with the one before
s = 'abcvabcdefga'
current = 0
biggest = 0
for i in range(1,len(s)): # compares the index[1] with [0] , 2 with 1 etc
if s[i] >= s[i-1]: # this char is bigger/equal last char
current += 1
biggest = max(current,biggest)
else:
current = 1
print biggest
You have to edit out the else statement. Because consider the case where the current just exceeds longest, i.e, from current = 3 and longest =3 , current becomes 4 by incrementing itself. Now here , you still want it to go inside the if current > longest statement
s = 'abcv'
longest = 1
current = 1
for i in range (len(s) - 1):
if s[i] <= s[i+1]:
current += 1
#else:
if current > longest:
longest = current
current = 0
i += 1
longest = current
print longest
Use a while condition loop, then you can easy define, at what condition your loop is done.
If you want QualityCode for longterm:
While loop is better practice than a break, because you see the Looping condition at one place. The simple break is often worse to recognize inbetween the loopbody.
At the end of the loop, current is the length of the last substring in ascending order. Assigning it to longest is not right as the last substring in ascending is not necessarily the longest.
So longest=max(current,longest) instead of longest=current after the loop, should solve it for you.
Edit: ^ was for before the edit. You just need to add longest=max(current,longest) after the for loop, for the same reason (the last ascending substring is not considered). Something like this:
s = 'abcv'
longest = 1
current = 1
for i in range (len(s) - 1):
if s[i] <= s[i+1]:
current += 1
else:
if current > longest:
longest = current
current = 0
i += 1
longest=max(current,longest) #extra
print longest
The loop ends when there is no code after the tab space so technically your loop has already ended

What's wrong with my for loop? Python

This for loop should iterate over even 'lines' in my input, as it holds the users name which I would like to place in a dictionary as a key, with a dictionary inside that key. My output does include the information I needed, but also odd lines which I do not want.
I'm new to python so I'm still trying to understand syntax.
Here's my code:
def get_name(string_input):
split_fullstop = string_input.split('.')
list = [] #creates a list
for line in split_fullstop:
count = 0
if count % 2 == 0: #if count is even
list.append(line.split('is connected to')) #add info to 'list'
count += 1 #increase count
names = {name[0]:{} for name in list}
return names
And here's the output after printing the function:
{'': {}, 'Levi ': {}, 'Bryant ': {}, 'Jennie likes to play Super Mushroom Man, Dinosaur Diner, Call of Arms': {}, 'Olive likes to play The Legend of Corgi, Starfleet Commander': {}, 'Debra likes to play Seven Schemers, Pirates in Java Island, Dwarves and Swords': {}, 'Levi likes to play The Legend of Corgi, Seven Schemers, City Comptroller: The Fiscal Dilemma': {}, 'Walter ': {}, 'Robin ': {}, 'John ': {}, 'Walter likes to play Seahorse Adventures, Ninja Hamsters, Super Mushroom Man': {}, 'Debra ': {}, 'Freda likes to play Starfleet Commander, Ninja Hamsters, Seahorse Adventures': {}, 'Mercedes likes to play The Legend of Corgi, Pirates in Java Island, Seahorse Adventures': {}, 'Ollie ': {}, 'Robin likes to play Call of Arms, Dwarves and Swords': {}, 'Bryant likes to play City Comptroller: The Fiscal Dilemma, Super Mushroom Man': {}, 'Freda ': {}, 'Olive ': {}, 'Mercedes ': {}, 'John likes to play The Movie: The Game, The Legend of Corgi, Dinosaur Diner': {}, 'Jennie ': {}, 'Ollie likes to play Call of Arms, Dwarves and Swords, The Movie: The Game': {}}
Remember that all code at the same indentation level below the for-loop will be run EACH iteration. Therefore you are redefining the variables count and names at each item the for-loop goes through. As mentioned in one of the comments, names should be at the same indentation level as the return statement.
Redefining count at each iteration means you will always find 0 % 2 == 0. It should be defined BEFORE the for-loop. Also, you only increment count when you run the #if count is even portion. So, assuming count is defined before the loop, you will see 0 as even, increment count and be left with an odd value of 1 forever.
Look at looping though indices and values simultaneously using enumerate. That way you need only check the even/odd value of the index.
maybe your count is a error indentation, count is design to filter even line.
for line in split_fullstop:
count = 0
if count % 2 == 0: #if count is even
list.append(line.split('is connected to')) #add info to 'list'
count += 1 #increase count
So you have used a "for each loop", which loops over every element in the iterable and built in functionality to only evaluate the even indexes. Instead of this, I think it is more clear and clean to use the function range.
range(0, len(split_fullstop), 2)
Evaluating only the even
I'll just focus on your count variable, because that's the first thing that tells me there's an error:
for line in split_fullstop:
count = 0
if count % 2 == 0: #if count is even
# some code
count += 1 #increase count
#some code
return names
First of all, you're resetting the count variable on each loop with that count = 0 inside the loop, so on EVERY loop count%2 will be equal to 0. This line should be OUTSIDE (before) the loop.
Second, you're increasing the variable inside that if condition count%2 == 0, if in one iteration, count == 0, then it will enter the if-part, and will increase the value to count == 1.
In the next (and all other) iteration, since count == 1, the inside of the if-part won't be executed and thus the count variable won't change.
So, it should be like:
count = 0
for line in split_fullstop:
if count % 2 == 0: #if count is even
#some code
count += 1 #increase count
return names
Note: Don't use built'in variables such as list because you'll overwrite them and it could lead to the unexpected behaviour in future. Use l for example for that.
Your line with names = {name[0]:{} for name in list} will be executed every step because it placed not in the same position as if statement. For steps where count % 2 == 1 you'll add to your dict empty lists. But in your solution you redefine count in each step so you'll never get that as #Isaac Drachman mentioned. So just delete some spaces or tab and define count before for loop:
def get_name(string_input):
split_fullstop = string_input.split('.')
l = [] #creates a list
count = 0
for line in split_fullstop:
if count % 2 == 0: #if count is even
l.append(line.split('is connected to')) #add info to 'list'
count += 1 #increase count
names = {name[0]:{} for name in l}
return names
Or you could rewrite it with list comprehension and enumerate:
def get_name(string_input):
l = [line.split('is connected to') for i, line in enumerate(string_input.split('.')) if i % 2 == 0]
names = {name[0]:{} for name in l}
return names

Loop Issue with Local Variable

I'm using Python (3.x) to create a simple program for an assignment. It takes a multiline input, and if there is more than one consecutive whitespace it strips them out and replaces it with one whitespace. [That's the easy part.] It must also print the value of the most consecutive whitespaces in the entire input.
Example:
input = ("This is the input.")
Should print:
This is the input.
3
My code is below:
def blanks():
#this function works wonderfully!
all_line_max= []
while True:
try:
strline= input()
if len(strline)>0:
z= (maxspaces(strline))
all_line_max.append(z)
y= ' '.join(strline.split())
print(y)
print(z)
if strline =='END':
break
except:
break
print(all_line_max)
def maxspaces(x):
y= list(x)
count = 0
#this is the number of consecutive spaces we've found so far
counts=[]
for character in y:
count_max= 0
if character == ' ':
count= count + 1
if count > count_max:
count_max = count
counts.append(count_max)
else:
count = 0
return(max(counts))
blanks()
I understand that this is probably horribly inefficient, but it seems to almost work. My issue is this: I would like to, once the loop is finished appending to all_lines_max, print the largest value of that list. However, there doesn't seem to be a way to print the max of that list without doing it on every line, if that makes sense. Any ideas on my convoluted code?
Just print the max of all_line_max, right where you currently print the whole list:
print(max(all_line_max))
but leave it at the top level (so dedent once):
def blanks():
all_line_max = []
while True:
try:
strline = input()
if strline:
z = maxspaces(strline)
all_line_max.append(z)
y = ' '.join(strline.split())
print(y)
if strline == 'END':
break
except Exception:
break
print(max(all_line_max))
and remove the print(z) call, which prints the maximum whitespace count per line.
Your maxspaces() function adds count_max to your counts list each time a space is found; not the most efficient method. You don't even need to keep a list there; count_max needs to be moved out of the loop and will then correctly reflect the maximum space count. You also don't have to turn the sentence into a list, you can directly loop over a string:
def maxspaces(x):
max_count = count = 0
for character in x:
if character == ' ':
count += 1
if count > max_count:
max_count = count
else:
count = 0
return max_count

Categories