How to get one iteration printed in a nested loop - python

I have a nested loop in python:
append_str = "//mycomment "
for item in runfile:
for item1 in flat_common_list:
item1 = item1[1:-1] ## remove double quotes otherwise match wont work
if item1 in item:
pre_comment = append_str + item
runfile_final.write(pre_comment)
else:
runfile_final.write(item)
break
My goal is to print all "items" in "runfile" once but prefix //mycomment to the matching lines with item1 in flat_common_list. Eventually write the results to runfile_final.
With the current code, it's working but only for the first match and then breaks. If I don't add a break, then everything is repeated in nested loop.

Move your break up to the case where the item matches and then dedent your else so that it only runs if the for doesn't break. If an item matches, you write once then break. If no items match, the else prints the original item. I moved stripping the quotes out of the loop so it is only done once.
append_str = "//mycomment "
# strip quotes from common list values for later match
fixed_common_list = [val[1:-1] for val in flat_common_list]
for item in runfile:
for item1 in flat_common_list:
if item1 in item:
pre_comment = append_str + item
runfile_final.write(pre_comment)
break
else:
runfile_final.write(item)

You need to organise your loops a bit differently. Keep track of the value you want to write to runfile_final, then write it once you are out of the inner loop:
for item in runfile:
modified_item = item
for item1 in flat_common_list:
item1 = item1[1:-1]
if item1 in item:
modified_item = append_str + item
break
runfile_final.write(modified_item)

Related

How to do something else at the end of an iteration

I have a list that contains some strings , I want to add some predefined values before every string in a list but the value at the end of the iteration should be different
Here is the list
lst = ['USER_INVITE','USER_LEAVE','GIVEAWAY_START','GIVEAWAY_EDIT','USER_INVITE','USER_LEAVE']
the expected output is
<:878677713269968896:909470525108154399> USER_INVITE
<:878677713269968896:909470525108154399> USER_LEAVE
<:878677713269968896:909470525108154399> GIVEAWAY_START
<:878677713269968896:909470525108154399> GIVEAWAY_EDIT
<:878677713269968896:909470525108154399> USER_INVITE
<:878677686350934027:910454682219085834> USER_LEAVE
here you can see the value before USER_LEAVE is different than others
I can simply do something like this to put these values before strings without a loop
logs = '<:878677713269968896:909470525108154399>\n'.join(map(str,keys[I]))
maybe iteration will help in this case by doing something else at the end of the loop
Using iteration, and some control flow logic around identifying the last item in the list, this can be done as follows:
output_str = ""
for i, item in enumerate(lst):
if i == len(lst) - 1: # Logic for identifying the last element
prefix = '<:878677686350934027:910454682219085834>'
else: # If not the last element in the list, do this:
prefix = '<:878677713269968896:909470525108154399>'
output_str += f'{prefix} {item}\n'
output_str = ""
for item in lst[:-1]:
output_str += f'<:878677686350934027:910454682219085834> {item}\n'
output_str += f'<:878677713269968896:909470525108154399> {lst[-1]}'
You can just work on every key but the last and then combine the output at the end.
a = "\n".join('<:878677713269968896:909470525108154399>' + key for key in lst[:-1])
b = '<:878677686350934027:910454682219085834>' + lst[-1]
a + b
'<:878677713269968896:909470525108154399>USER_INVITE\n<:878677713269968896:909470525108154399>USER_LEAVE\n<:878677713269968896:909470525108154399>GIVEAWAY_START\n<:878677713269968896:909470525108154399>GIVEAWAY_EDIT\n<:878677713269968896:909470525108154399>USER_INVITE<:878677686350934027:910454682219085834>USER_LEAVE'

i dont know what is wrong with my code. When i run the code it is just in a loop and wont stop the loop

Here is the assignment
and here is the code
shoppinglist = []
user = shoppinglist.append(input("Enter your items "))
while user != 'end':
user = shoppinglist.append(input())
shoppinglist.sort()
no_items = len(shoppinglist)
print(no_items)
the loop condition was while user != 'end' but even if i input end the loop doesn't stop.
shoppinglist.append() returns None, not the item that was appended.
Since append puts the item on the end, you can see what got appended by taking the [-1] list element:
shoppinglist = []
shoppinglist.append(input("Enter your items "))
while shoppinglist[-1] != 'end':
shoppinglist.append(input())
shoppinglist.pop() # remove the last element, which is "end"

Python code not appending 'Free Period' when I want it to

list1 = []
elective = []
prereq = []
someNumber = 1
dict2 = {
1: SEM2period1, 2: SEM2period2,
2: SEM2period3, 4: SEM2period4,
5: SEM2period5, 6: SEM2period6,
7: SEM2period7, 8: SEM2period8
}
for key, dlist in dict2.items():
if not dlist:
list1.append("Free Period")
someNumber += 1
continue
for item in dlist:
if item in list1:
continue
elif item in elective:
elecStorage.append(item)
elif item in prereq:
list1.append(item)
someNumber += 1
break
if someNumber > len(list1):
for index in elecStorage:
if index in list1:
break
else:
list1.append(index)
someNumber += 1
elecStorage[:] = []
break
Notes: Electives and Prereq both contain strings like "Calculus 1" (for prereq), or "Astronomy" (for elective.) The variables in dict2 are lists that contain class (as in classroom) names that were called earlier by the function.
What the snippet that starts out with "for key, dlist in dict2.items()" should do is search through the the elements of the first list, checking first if there is a list, if there isn't then append "Free Period" into the list. Then it should check if any of the elements of the list exist in prereq, and finally if there isn't, append something from electives into it. (Because if it gets past the first condition, it's safe to assume there is at least an elective.) and then loop back around and perform the same operation to the next list of elements.
Issue is, unless all of the lists contain nothing, it won't append 'Free Period' and I can't figure out why.
Ideas?
Something in your SEM*period* is likely returning an empty list, and not None. The correct checks for empty list '[]', is 'if list1 == []' or 'if len(list1) == 0'.
None is placeholder meaning a non-existing object. [] is a valid list object, it just has no entries in the list. 'if not foo' is simply checking for None, not an empty list.
You should verify the contents of your SEM2period variables, this is hard to diagnose without them. I didn't follow the rest of your logic, but it's really just the first block in the loop that you are interested in, yes? You may have a list containing an empty list, perhaps? That would mess up your logic:
d2 = {1:['elec'], 2:[]}
for key, dlist in d2.items():
if not dlist:
print 'empty!'
else:
print dlist
gives you
['elec']
empty!
but
d2 = {1:['elec'], 2:[[]]}
for key, dlist in d2.items():
if not dlist:
print 'empty!'
else:
print dlist
gives you
['elec']
[[]]

Reference next item in list: python

I'm making a variation of Codecademy's pyglatin.py to make a translator that accepts and translates multiple words. However, I'm having trouble translating more than one word. I've been able to transfer the raw input into a list and translate the first, but I do not know how to reference the next item in the list. Any help would be greatly appreciated.
def piglatin1():
pig = 'ay'
original = raw_input('Enter a phrase:').split(' ')
L = list(original)
print L
i = iter(L)
item = i.next()
for item in L:
if len(item) > 0 and item.isalpha():
word = item.lower()
first = word
if first == "a" or first == "e" or first == "i" or first == "o" or first =="u":
new_word = word + pig
print new_word
else:
new_word = word[1:] + word[0:1] + pig
# first word translated
L = []
M = L[:]
L.append(new_word)
print L # secondary list created.
again = raw_input('Translate again? Y/N')
print again
if len(again) > 0 and again.isalpha():
second_word = again.lower()
if second_word == "y":
return piglatin()
else:
print "Okay Dokey!"
else:
print 'Letters only please!'
return piglatin1()
I was working on this problem recently as well and came up with the following solution (rather than use range, use enumerate to get the index).
for index, item in enumerate(L):
next = index + 1
if next < len(L):
print index, item, next
This example shows how to access the current index, the current item, and then the next item in the list (if it exists in the bounds of the list).
Here are a few things to note that might help.
The lines i = iter(L) and item = i.next() are unnecessary. They have no effect in this method because you are redefining item immediately afterwards in the line for item in L. Go ahead and comment out those two lines to see if it makes any changes in your output.
The looping construct for item in L will go once over every item in the list. Whatever code you write within this loop will be executed once for each item in the list. The variable item is your handle to the list element of an iteration.
If, during any iteration, you really do want to access the "next" element in the list as well, then consider using a looping construct such as for i in range(0,len(L)). Then L[i] will be the current item and L[i+1] will you give the subsequent item.
There are some slight issues with the code but I think there is one main reason why it will not repeat.
In order to process the entire string the
again = raw_input('Translate again? Y/N')
and it's succeeding lines should be brought outside the for statement.
Also you appear to be setting L to an empty string inside the loop:
L = []
The following is a modified version of your code which will loop through the entire sentence and then ask for another one.
def piglatin():
pig = 'ay'
while True:
L = raw_input('Enter a phrase:').split(' ')
M = []
for item in L:
if len(item) > 0 and item.isalpha():
word = item.lower()
first = word
if first == "a" or first == "e" or first == "i" or first == "o" or first =="u":
new_word = word + pig
print new_word
else:
new_word = word[1:] + word[0:1] + pig
M.append(new_word)
else:
print 'Letters only please!'
print M # secondary list created.
again = raw_input('Translate again? Y/N')
print again
if len(again) > 0 and again.isalpha():
second_word = again.lower()
if second_word == "n":
print "Okay Dokey!"
break
Changes made:
You don't need to cast the return of the split to a list. The split
return type is a list.
It isn't necessary to make an iterator, the for loop will do this for you.
I removed the function as the return type. I'm assuming you were attempting some form of recursion but it isn't strictly necessary.
Hope this helps.
Step by step:
If you set variable original in this way:
original = raw_input('Enter a phrase:').split()
it will be already a list, so need to additional assignment.
What is the purpose of these lines?
i = iter(L)
item = i.next()
In a loop, you assign variable to the word, when it is actually only the first letter of the word, so it’ll be better like this: first = word[0]
Then if you want to check if first is a vowel, you can just do:
if first in 'aeuoiy'
Answer to your actual question: do not assign L to an empty list!
If you want to repeat the action of a function, you can just call it again, no need to rewrite the code.

if statement to test 2 string but there isn't output?

My goal here is trying to match the list of strings against list of ints:
For example my list of strings: wholelookup[uniprotID] = [A177T,I126T,M418T].
My list of ints: lookup[uniprotID] = [177,126,418].
If there is a match then I would like to print the token in wholelookup.
Here is what i have so far but it didn't print anything as the result:
for item in lookup[uniprotID]:
for names in wholelookup[uniprotID]:
if start <= item <= end and re.match(item, names) :
item, start, end = map(int, (item, start, end))
print names
match tries to match from the beginning. Also: you do not want to match a 1 to for instance a321a .
You could use 're.match(r'\w'+str(item)+r'\w', names)' instead of re.match(item, names)
Or use re.search:
re.search(r'\d+',names).group(0)==item
Why use a regex at all?
Assuming start and end are already ints and item is a string, try this:
for item in lookup[uniprotID]:
if start <= int(item) <= end: continue
for names in wholelookup[uniprotID]:
if str(item) in names :
print names

Categories

Resources