Below is my code: I am trying to turn the loop results I get from this code into a list. Any ideas?
import requests
from bs4 import BeautifulSoup
page = requests.get('http://forecast.weather.gov/MapClick.php?lat=37.7772&lon=-122.4168')
soup = BeautifulSoup(page.text, 'html.parser')
for x in soup.find_all(class_='tombstone-container'):
y = (x.get_text())
print (y)
A straightforward way to convert the results of a for loop into a list is list comprehension.
We can convert:
for x in soup.find_all(class_='tombstone-container'):
y = (x.get_text())
print (y)
into:
result = [x.get_text() for x in soup.find_all(class_='tombstone-container')]
Basic (list comprehension has a more advanced syntax) has as grammar:
[<expr> for <var> in <iterable>]
it constructs a list where Python will iterate over the <iterable> and assigns values to <var> it adds for every <var> in <iterable> the outcome of <expr> to the list.
if you don't want to change much of your code, create an empty list before your loop like this
myList = []
and in your loop append the content like this:
myList.append(str(x.get_text())) # EDIT2
EDIT1:
The reason I used myList.append(...) above instead of myList[len(myList)] or something similar, is because you have to use the append method to extend already existing lists with new content.
EDIT2:
Concerning your problem with None pointers in your list:
If your list looks like [None, None, ...] when printed after the for loop, you can be sure now that you have still a list of strings, and they contain the word None (like this ['None','None',...]).
This would mean, that your x.get_text() method returned no string, but a None-pointer from the beginning. In other words your error would lie buried somewhere else.
Just in case. A complete example would be:
myList = []
for x in soup.find_all(class_='tombstone-container'):
# do stuff, but make sure the content of x isn't modified
myList.append(str(x.get_text()))
# do stuff
Just loop over it.
map(lambda x: x.get_text(), soup.find_all(class_='tombstone-container'))
Related
I am trying to fix some broken linux paths in a list I am working with.
List:
mylist = ['/root/path/path', '/cat', '/dog', '/root/path/path', '/blue', '/red']
Requirements:
If element does not begin with '/root', join to the element to the left of it.
Code so far:
mylist2 = [''.join(x) for x in mylist]
print(mylist2)
Expected output:
['/root/path/path/cat/dog', '/root/path/path/blue/red']
Actual output:
['/root/path/path', '/cat', '/dog', '/root/path/path', '/blue', '/red']
I've also tried:
mylist2 = [''.join(x) if myroot not x for mylist]
...which produces a syntax error...
Any ideas on what I am doing wrong?
This is simpler if you just use a regular loop. The problem with the list comprehension is that you don't have a uniform operation on each element of the first list that creates an element for the new list. (Think of a list comphension as a combination of map and filter. You can map one old value to one new value, or drop an old value, but you can't combine multiple old values into a single new value.)
mylist2 = []
for path in mylist:
if path.startswith('/root'):
mylist2.append(path)
else:
mylist2[-1] += path
(This is only partially correct; it assumes the first element of mylist will actually start with /root, so that mylist2[-1] will never be used if mylist2 is empty.)
This is one method using list comprehension:
mylist2 = ['/root' + x for x in ''.join(mylist).split('/root') if x] # if x eliminates the empty split elements
# ['/root/path/path/cat/dog', '/root/path/path/blue/red']
Since your goal is basically to join everything and then split them by /root, this line of list comprehension does exactly that and adds /root back to each element.
But as you can see, given just the code, #chepner's answer is much more understandable and clearer. Just because list comprehension exist doesn't mean it should be your go-to.
Also I should note, if there's /root within any of your elements (not necessarily at the beginning), this code will also separate it because of the split, so it's not as exact as explicitly going through the loop. If you wanted to handle that scenario it becomes very ugly...:
['/root' + y for y in ''.join("_" + x if x.startswith("/root") else x for x in lst).split("_/root") if y]
# eww
Please let me know how this for loop is working.
points = {0,1,2,3,4,8,1}
x = float(sum([len(points) for i in points]))
print(x)
This code snippet is giving me output as:-
36.0
List comprehensions are not that hard if you take a look at a very simple example:
[T(x) for x in X]
The first term is declaring what should be done with all the individual items in the collection we are iterating over. This might be type conversion or just extracting a specific value from a dict.
The symbol after the for just defines the name for our iteration variable and the last term is the collection(list, set, dict etc.) which we iterate through.
A more verbose implementation of the same thing could be:
result = []
for i in range(len(X)):
result.append(T(X[i]))
After this the content of result is the same as the list returned by the list comprehension.
I am currently writing a small bit of logic for my HTML page. My aim is to create variables (lists) within an iteration (using the iteration to create the names of said lists as the amount of them will be unknown to the program). I am currently creating the lists like this:
maps={}
currentMap = elements[0].process
counter=0
for i in elements:
if(counter==0):
maps["mapsEle{0}".format(counter)]=[]
counter+=1
if(i.process!=currentMap):
currentMap = i.process
maps["mapEle{0}".format(counter)]=[]
counter+=1
else:
print("No change found, keeping heading the same.")
However as you can probably tell, this does not create a list but a string. I try to print the variables (e.g. mapsEle0) and it returns the variable name (e.g. print(mapsEle0) returns "mapsEle0") this too me is suprising as I would have thought if the dictionary is saving it as a string it would print "[]".
So I am looking for a way to create lists within the dictionary in that iteration I am using there, basically want to just reformat my declaration. Cheers in advance everyone :)
Edit:
As requested here is the code where I attempt to append. Please note I want to append 'i' into the lists and no the dictionary.
for i in maps:
for x in elements:
if(x.process!=currentMap):
currentMap=x.process
elif(x.process==currentMap):
#i.append(x)
The syntax of your print statement is wrong, if you want to access the contents of the dictionary, you need to use different notation.
Instead of print('mapsEle0') you need to do print(maps['mapsEle0']).
Update:
Unfortunately your description of what you want and your code are a bit conflicting, so if you can, please try to explain some more what this code is supposed to do.
for i in maps.iterkeys():
for x in elements:
if(x.process!=currentMap):
currentMap=x.process
elif(x.process==currentMap):
maps[i].append(x)
This will iterate over all keys of maps ('mapsEle0'...'mapsEleN') and add x to the contained list if the elif condition is fulfilled.
You're printing the string by doing print('mapsEle0').
To print the dict, you must print(maps) - 'll print the whole dictionary, OR, to print a specific key/element print(maps['mapsEle0'])
To elaborate it further here's a interpreter session:
>>> maps = {}
>>> counter = 0
>>> maps["mapsEle{0}".format(counter)]=[]
>>> maps
{'mapsEle0': []}
>>>
>>> print(maps)
{'mapsEle0': []}
>>>
>>> print(maps['mapsEle0'])
[]
>>>
For the append part:
>>> maps['mapsEle1'].append('hello')
>>> print(maps['mapsEle1'])
['hello']
Edit 2: Your statement is still not clear
As requested here is the code where I attempt to append. Please note I
want to append 'i' into the lists and no the dictionary.
I think sobek has got it right - you want to append x to the mapsEle0, mapsEle1 lists, which are keys in maps dictionary.
for i in maps.iterkeys():
for x in elements:
if(x.process!=currentMap):
currentMap=x.process
elif(x.process==currentMap):
maps[i].append(x)
so i want to remove an item from a list and store it into the variable at the same time in python. I tried a sample code like this:
rvals = []
rvals.append("row")
r = rvals.remove("row")
print(r)
but it turns out this doesnt really work and it gives r a NoneType value instead of removing what i wanted and storing it. Is there a way to do this?
list.remove(x)
Remove the first item from the list whose value is x. It is an error
if there is no such item.
So, as stated in the docs, you will not get the value returned.
This can help:
value = "row"
rvals = []
rvals.append(value)
print rvals.pop(rvals.index(value))
Or just use pop(), if you only want to remove and get the last inserted item:
value = "row"
rvals = []
rvals.append(value)
print rvals.pop()
Output:
row
Printing a removed element from the list using remove() method generally results in None.
Hence, a better approach is to, first store the element to be removed and then remove it from the list.
I've got the list student:
student = ["test_name","1","6"]
And I've got the read data sublist:
read_data = [["test_name","1","2","5","9"],["test_name_2","1","5","2","10"]]
I've written the following nested loop to return the index of a sublist (referred to as x) in read_data if student[0] == x[0]:
lst = [read_data.index(x) for x in read_data if x[0] == student [0]]
So I'm looping through each item in read data and (if x[0] == student[0]) the index of the sublist should be stored in lst.
When I try to use this in the index parameter of a list to insert data like so:
read_data[read_data.index(x) for x in read_data if x[0] == student[0]].insert(2,student[0])
I get an error saying generators can't be used for indexes - why not?
I can obviously just use the integer stored in lst but this seems inefficient - surely there's a way to do this on one line.
Is there some better alternative method to checking if a string is in any of a read_data's sublists and getting the index of this sublist?
In the assignment to lst you are creating a list. But in the snippet below that, you have merely taken the interior of that list expression and are trying to use it as an index. To fix your specific example, you would need to change:
read_data[iter_expr]
to:
read_data[[iter_expr][0]]
That will use the first value in the list as the index.
There are better ways to do this, but this is probably the smallest change that will fix the specific problem you asked about.
I dont know why you would want to do this but then you need to put brackets around the list comprehension and get index the first match of it like this:
read_data[[read_data.index(x) for x in read_data if x[0] == student[0]][0]].insert(2, student[0])
Remember if the list comprehension produces an empty list, you will encounter an IndexError.