Seriously elusive for loop (racking my brains!) - python

I've got a loop issue in Python 2.72 that's really frustrating me. Basically the loop is not iterating on the first index j, and I've tried all sorts of ways to fix it with no luck.
def learn(dataSet):
for i in dataSet.getNext():
recall = raw_input("Enter all members of %s you are able to recall >>> (separated by commas) " % (i.getName()))
missed = i.getMembers()
missedString = []
for a in missed:
missedString.append(a.getName())
Here is the loop I can't get to iterate. The first for loop only goes through the first iteration of j in the split string list, then removes it from missedString. I would like for all members of the split-string recall to be removed from missedString.
for j in string.split(recall, ','):
if j in missedString:
missedString.remove(j)
continue
for b in missed:
if b.getName() not in missedString:
missed.remove(b)
print 'You missed %d. ' % (len(missed))
if (len(missed)) > 0:
print 'Maybe a hint or two will help...'
for miss in missed:
remind(miss.getSecs(), i.getName(), missed)
How can I fix the above code?

missedString is a terrible name for a list
Note that you can simplify your code in a few places
missedString = []
for a in missed:
missedString.append(a.getName())
can be replaced by a list comprehension
missedString = [a.getName() for a in missed]
Here you should just use the split method of recall instead of string.split). It looks as though this loop is supposed to be nested inside the for i loop, so I will assume it is (If it's not, you will be using the wrong value of recall with the wrong dataset).
for j in string.split(recall, ','):
if j in missedString:
missedString.remove(j)
continue
It can also be replaced by a list comprehension.
recall_set = set(recall.split(','))
missedString = [j for j in missedString if j not in recall_set]
This will not work properly if eg. the user enters extra spaces in the input, so it's a good idea to strip() those elements
recall_set = set(s.strip() for s in recall.split(','))
missedString = [j for j in missedString if j not in recall_set]
This loop has a serious problem. In general it's not a good idea to remove elements from the list you are iterating over. You'll end up skipping over some elements without checking them
for b in missed:
if b.getName() not in missedString:
missed.remove(b)
Maybe a list comprehension can help again
missed = [b for b in missed if b.getName() in missedString]

In this code
for j in string.split(recall, ','):
if j in missedString:
missedString.remove(j)
continue
try adding an
else:
print 'Didn't remove "%s"' % j
(And get rid of the continue. It's not serving any purpose).
You probably are missing some whitespace from your split. If that's the case, add a j = j.strip() or use re.split(r'\s*,\s*', recall) in place of string.split(recall, ',').

Related

finding a list of perfect integers from a range of integer numbers

the user will input a arbitrary range where the end number is the number up to what the user wants perfect numbers from those numbers and append the numbers in a list and print the list or the list elements...
Sample CODE:
sum_1=0
sum_2=0
b=[]
a=range(1,int(input('enter_num_upto you want perfect num')))
for i in a:
for items in range(1,i):
if(i%items)==0:
sum_1=sum_1+items
sum_2=sum_2+items+i
if sum_1==i and (sum_2//2)==i:
b.append(i)
for j in b:
print(j)
the code runs without errors but it doesn't display any outputs..... please mark my mistakes and explain the correct logics
THANKS IN ADVANCE
I think the problem is that you haven't defined the list "b". I'd suggest that after you define
a=range(1,int(input('enter_num_upto you want perfect num')))
define b as
b=[]
This will tell the program that a list "b" exists, which you can then append items to. You can't append items to a list that doesn't exist yet.
The same thing should go for the 2 variables sum_1 and sum_2, you cannot define them conditionally in an "if statement", therefore you should define them at the beginning of your program, right after you define b
sum_1 = 0
sum_2 = 0
As for the logic of your code, I suggest you don't need a sum_2, after going through the for loop that makes sum_1, check if sum_1 is equal to i. But make sure whenever you use "range", you set the end as the number after you want to end it at. For example if you want the range to start at 1 and end at I, use range(1,i+1). This is only for your input. Make sure to set sum_1 back to 0 after every iteration aswell.
so:
a=range(1,int(input('enter_num_upto you want perfect num'))+1)
b=[]
sum_1=0
for i in a:
for item in range(1,i):
if (i%item)==0:
sum_1= sum_1+item
if sum_1==i:
b.append(i)
sum_1=0
for j in b:
print(j)

Am I doing this right? Removing items from python list - is there room for optimization?

I have 2 lists. I want to remove all items from list which contain strings from second list. Now, I am using classical 2 loop approach, 1st I loop over copy of main list and then for every item i check if it contains any strings from 2nd list. Then I delete the item if string is found. And I can end the 2nd loop with break, since no more lookup is needed (we're gonna remove this line anyway). This works just fine - as you can see, I am iterating over copy of list, so removing elements is not a problem.
Here is the code:
intRemoved = 0
sublen = len(mylist) + 1
halflen = sublen / 2
for i, line in enumerate(mylist[:], 1):
for item in REM:
if item.encode('utf8').upper() in line.text.encode('utf8').upper():
if i < halflen:
linepos = i
else:
linepos = (sublen - i) * -1
mylist.remove(line)
intRemoved += 1
break
Now, I need data how many lines I removed (intRemoved) and position in the list (from beginning of list or end of list, that's why it splits in half). Positive numbers indicate removed line position from the beginning of the file, negative from end.
Ahh, yes, and I am ignoring the case. That's why there is .upper().
Now, since I am in no way pro, I just need to know if I am doing it right, performance-wise? Am I doing something that's bad for performance? Is there a way to optimize this?
Thanx,
D.
As you have been said, probably you should be looking in codereview. Anyhow, I am pretty sure using sets and intersection operation is going to be much faster.
Take a look here: https://docs.python.org/2/library/stdtypes.html#set
Calling encode is unnecessary. Calling upper each time is not ideal. Coping the list for iterating is expensive. Removing is more expensive, since one have to search for the element and shifting elements. Counting intRemoved is not the best way, either.
sublen = len(subsSrt) + 1
halflen = sublen / 2
filtered_list = []
rem_upper = [item.upper() for item in REM]
for i, line in enumerate(mylist, 1):
text = line.text.upper()
if any(item in text for item in rem_upper):
if i < halflen:
linepos = i
else:
linepos = (sublen - i) * -1
else:
filtered_list.append(line)
intRemoved = len(mylist) - len(filtered_list)

Printing a number as a sum of powers of 2 in increasing order

I am trying to print out a decimal integer(non-negative) as sum of powers of 2 i.e for input 10, it should print "2 8" without quotes. I already wrote this code, but can someone give me a one liner for this.
n = bin(int(raw_input()))[-1:1:-1]
print (' ').join([str((int(n[j])+1)**j) for j in xrange(len(n)) if n[j] == '1'])
It much better to have this spread across muplitple lines, and using and input inside a list comprehension hides a key piece of the information of what your code is doing.
Ultimately, what you are asking to doisn't pretty, but here it is anyway:
print (' ').join([str(2**i) for i,j in enumerate(bin(int(raw_input()))[-1:1:-1]) if j == '1'])
Pretty printed it is:
print ' '.join(
[str(2**i)
for i,j in enumerate(
bin(int(raw_input()))[-1:1:-1]
)
if j == '1']
)
Notes:
int(n[j])+1) will always be 2, since you are only iterating if j is 1.
enumerate returns a list of tuples each containing the index and value, so you don't need to store n, and can test against j directly.
Python can iterate over a list of items without having to fetch them by index, its the difference between [list[i]**2 for i in len(list)] and [i**2 for i in list]
You don't need to put brackets around the string, so you can save some space by doing this:
" ".join(...)
Instead of this:
(" ").join(...)

Creating multiple list from loops

I want to make multiple lists with my for loops, My code is:
for port in portlist1:
print port.getname(),port.getsize()
for register in port.getregisters():
j=j+1
print j
j=0
Output is:
B 10
1
C 15
1
F 30
1
I want to make list every time:
List1=[[B,10],1]
List2=[[C,15],1]
List3=[[F,30],1]
Can someone help me here?
lists = []
for port in portlist1:
l = [[port.getname(), port.getsize()]]
for register in port.getregisters():
j=j+1
l.append(j)
lists.append(l)
j=0
It's not clear what was the value of j before the loop, but it looks like you are using it to measure the length of port.getregisters(). Try this one-liner:
result = [[[port.getname(), port.getsize()], len(port.getregisters())] for port in portlist1]
It's a bad idea to make a new list each time, you should just go with nesting each list. If the amount of ports is static, you can use vars()['listX'].. But still not really recomended. You should go with the answer given by kroolik or alecxe
But if you REALLY need someting like..:
List1=[[B,10],1]
List2=[[C,15],1]
List3=[[F,30],1]
You can use:
lname = "list"
for i,p in enumerate(portlist1):
j = len(p.getregisters())
vars()[lname+str(i)] = [(p.getname(),p.getsize()), j]
print list0
print list1
print list2

Retrieve Innermost value inside one-line 2 for loops?

I am trying to get the value of j when name matches in i. But unfortunately all I am getting is the last element in Functions(). I guess this makes sense. But how is it possible to get value of j at the time name matches the list of GetFunctionName()'s?
Is there any one line code to do this?
func_ea = [j for i in [GetFunctionName(j) for j in Functions()] if name in i]
EDIT: Thanks eric for the solving the first problem
Would it be possible to reduce this further down to one liners?
def LocateBytesInFunctions(self, searchterm, *funcname):
foundaddress = []
for name in funcname:
func_ea = [i for i in Functions() if name in GetFunctionName(i)]
for startea in func_ea:
endea = GetFunctionAttr(startea, FUNCATTR_END)
self.debugprint("Start: " + hex(startea) + " End: " + hex(endea))
foundaddress.extend(self.LocateBytes(searchterm, startea, endea))
return foundaddress`
Since i is only used in one place, you can expand the inner comprehension:
func_ea = [j for j in Functions() if name in GetFunctionName(j)]
The inner comprehension is running to completion, so j is getting bound to the last result from Functions(). One way to fix this is to keep both j and GetFunctionName(j) around so that you can reference it later in the comprehension loop.
func_ea = [j for i, j in [(GetFunctionName(j), j) for j in Functions()]
if name in i]

Categories