for loop, and url.remove() only affecting every other entry [duplicate] - python

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 4 years ago.
Getting some confusing behaviour when running a for loop and removing entries from a list (cleaning out invalid urls):
urls = ['http://a.com/?mail=a#b.com','mailto:a#a.com', 'mailto:a#b.com', 'mailto:a#c.com', 'mailto:a#d.com']
for s in urls:
if '#' in s and '?' not in s:
urls.remove(s)
print(urls)
The output is:
['mailto:a#b.com', 'mailto:a#d.com']
It is consistently every other entry, so I'm assuming my understanding of python is not correct.
I looked into list comprehension with Python and ended up with:
urls = [s for s in urls if not ('?' not in s and '#' in s)]
This does what I want it to.
Is that the best way, can someone explain the behaviour, because I don't get it.
Thanks

The problem with your first solution is that you iterate over an object while deleting entries from it. The topic is discussed here for example: How to remove items from a list while iterating?

If you are trying to remove from list while iterating over, take a copy and iterate. urls[:] takes a copy of urls and you iterate over that. This prevents some unexpected situations that occur when iterating through the original list:
urls = ['http://a.com/?mail=a#b.com','mailto:a#a.com', 'mailto:a#b.com', 'mailto:a#c.com', 'mailto:a#d.com']
for s in urls[:]:
if '#' in s and '?' not in s:
urls.remove(s)
print(urls)
But, I would rather prefer the list-comprehension version of yours, that's more concise and pythonic.

Related

How to remove [' '] from string [duplicate]

This question already has answers here:
In the Python interpreter, how do you return a value without single quotes around it?
(2 answers)
Closed 2 years ago.
New guy here, I am currently writing a web scraper for an exercise and I have encountered a problem with extracting the url to re-use. Basically I managed to get the URL but when I print it, it is still showing the [' '] (for example: ['http://123.com'] so it cannot be used as an input.
I am extracting the string using re.findall but then I tried to use .strip and .replace but it's I'm either getting a traceback or the input remains the same. Any suggestions please?
Extract:
z = re.findall(r'(?=htt).*?(?<=htm)', y)
h = str(z)
h = h.strip('\['"')
print(h)
re.findall returns a list. Lists don't have strip or replace methods. Access the element of the list by using z[0]. You could also use re.search if you're only looking for one string.
Just like the answers in the comments, you can simply iterate over the list to access the elements inside like so:
for i in z:
print(i)
You can substitute other methods instead of the print statement.

How to remove "sub-lists" from a list? [duplicate]

This question already has answers here:
How do I make a flat list out of a list of lists?
(34 answers)
Closed 3 years ago.
I am having trouble creating a function since I want to be able to refer to the tuple and not the list which contains the tuples. Hence I have come to the conclusion that I want to get rid of the inner square brackets.
I have a list similar to this:
List=[[(1,2),(3,4),(5,6)],[(1,2),(5,7),(3,8)],[...],[...]]
So the question I am asking is how can I remove the inner [ ] so that I can just produce a single list of tuples.
Also, I am not sure if I am allowed to ask another question, but how would i also delete duplicates (x,y) entries in my new list?
I have not provided code for this since I know the problem for the code I have and I believe I would confuse people by including it. If however, you wish to see the code, or want me to clarify anything please let me know.
I think this has been asked and answered on here multiple times. The solution to the flattening problem would be as follows:
new_list = [tupl for l in List for tupl in l]

loop a list - length of list but do not need the item created, pythonic? [duplicate]

This question already has answers here:
Is it possible to implement a Python for range loop without an iterator variable?
(15 answers)
Closed 4 years ago.
This is going to be a bit silly of a question. I have a simple list:
my_list = ["apple", "orange", "car"]
And I'd like to run a loop for the length of that list, but I don't need anything in the list. I can clearly do this:
for item in my_list:
call_external_thingy()
Which would loop 3 times, perfect. However, I'm never using the item in my for loop. So while this does work, everytime I look at my code I feel that I've made a mistake, "Oh shoot, I didn't pass item in.. oh right I just need to run that command for the number of items in the list..."
What would be the more pythonic way to simply run a for loop for the number of items in a list without creating item. I'm thinking of something with len or range but can't get my head around it and anything I mock up just looks like a big mess.
Note, I'm tempted to put this on codereview instead, but they usually want all the code and a lot of why. This seems like a simple enough question to be here, but I could be wrong!
Thank you!
This is pythonic :
for _ in my_list:
call_external_thingy()
for i in range(len(my_list)):
call_external_thingy()

Why does .split() not appear to be working in this context? (Python) [duplicate]

This question already has answers here:
why is python string split() not splitting
(3 answers)
Closed 6 years ago.
I've got a simple block of code which is meant to iterate over a list of strings and split each item in the list into a new list, then call another function on each item:
list_input = take_input()
for item in list_input:
item.split()
system_output(item)
The problem is that 'item.split()' doesn't seem to be doing anything. With a print(item) statement in the penultimate line, all that is printed to the console is the contents of item, not the contents split into a new list. I feel like I'm missing something obvious, can anyone help? Thanks!
EDIT: So I've been informed that strings are immutable in Python, and in light of this replaced the 'item.split()' line with 'item = item.split()'. However, I am still running into the same error, even with item redefined as a new variable.
split() does not split the string inplace, it only returns a splitted string that you have to put in an other variable.

.remove() in Python list breaks a for loop [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 6 years ago.
I wrote a for loop that supposedly removes any elements that fits the description.
Example:
for tag in tags:
if tag.lower() in ['ex1', 'ex2', 'ex3']:
tags.remove(tag)
My tags would look like ['EX1', 'EX2', 'ex1', 'ex2', 'ex3', 'ex4', 'ex5'] and I expect to keep only ex4 and ex5
What I noticed is that the for loop would skip some elements, giving me results like ['EX2', 'ex2', 'ex4', 'ex5']
I suspect this being indexing issue, but I'm not sure if that's really the case.
I ended up using a list comprehension, which does the job correctly, but I just want to understand the true reason behind the unexpected behavior.
Python has a hard time iterating through something that is being changed during the iteration. You can instead use a copy:
for tag in tags[:]:
if tag.lower() in ['ex1', 'ex2', 'ex3']:
tags.remove(tag)

Categories

Resources