how this for loop is used in python - python

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.

Related

turning a loop into a list python

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'))

Sorting out unique elements from a list to a set

I was writing a function to save unique values returned by a list "list_accepted_car" to a set "unique_accepted_ant". list_car_id is list with the value ['12','18','3','7']. When i run the code i am getting error , "unhashable list ". Can anyone suggest me what is the error?
list_accepted_car = [] #set to store the value list_accepted_car
unique_accepted_car = set() #set to store the value unique_accepted_car
num_accepted = 2 #predifined value for the number of cars allowed to enter
def DoIOpenTheDoor(list_car_id): #list_ant_id is a list of cars allowed to enter
if len(list_accepted_car) < num_accepted:
if len(list_car_id) > 0:
list_accepted_car.append(list_car_id[0:min(len(list_car_id),num_accepted-len(list_accepted_car))])
unique_accepted_list = set(list_accepted_car)
print unique_accepted_list
return list_accepted_car
Under the assumption that list_car_id looks like: [1,2,3,4,5].
You add in list_accepted_car a sublist of list_car_id, so list_accepted_car will look like [[1,2]] i.e. a list of a list.
Then you should change
unique_accepted_list = set(list_accepted_car)
to
unique_accepted_list = set([x for y in list_accepted_car for x in y])
which will extract each element of the sublist and provide a flatten list. (There exists other options to flatten a list of list)
You are saving a list of lists, which can't be converted to a set. You have to flatten it first. There are many examples of how to do it (I'll supply one using itertools.chain which I prefer to python's nested comprehension).
Also, as a side note, I'd make this line more readable by separating to several lines:
list_accepted_car.append(list_car_id[0:min(len(list_car_id),num_accepted-len(list_accepted_car))])
You can do:
from itertools import chain
# code ...
unique_accepted_list = set(chain.from_iterable(list_accepted_car))
The best option would be to not use a list at all here, and use a set from the start.
Lists are not hashable objects, and only hashable objects can be members of sets. So, you can't have a set of lists. This instruction:
list_accepted_car.append(list_car_id[0:min(len(list_car_id),num_accepted-len(list_accepted_car))])
appends a slice of list_car_id to list_accepted_car, and a slice of a list is a list. So in effect list_accepted_car becomes a list of lists, and that's why converting it to a set:
unique_accepted_list = set(list_accepted_car)
fails. Maybe what you wanted is extend rather than append? I can't say, because I don't know what you wanted to achieve.

Creating multiple lists within a dictionary using an iteration

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)

Python: Using a nested for loop to produce the index for a sublist

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.

Build Dictionary in Python Loop - List and Dictionary Comprehensions

I'm playing with some loops in python. I am quite familiar with using the "for" loop:
for x in y:
do something
You can also create a simple list using a loop:
i = []
for x in y:
i.append(x)
and then I recently discovered a nice efficient type of loop, here on Stack, to build a list (is there a name for this type of loop? I'd really like to know so I can search on it a little better):
[x.name for x in y]
Ok, that being said, I wanted to go further with the last type of loop and I tried to build a python dictionary using the same type of logic:
{x[row.SITE_NAME] = row.LOOKUP_TABLE for row in cursor}
instead of using:
x = {}
for row in cursor:
x[row.SITE_NAME] = row.LOOKUP_TABLE
I get an error message on the equal sign telling me it's an invalid syntax. I believe in this case, it's basically telling me that equal sign is a conditional clause (==), not a declaration of a variable.
My second question is, can I build a python dictionary using this type of loop or am I way off base? If so, how would I structure it?
The short form is as follows (called dict comprehension, as analogy to the list comprehension, set comprehension etc.):
x = { row.SITE_NAME : row.LOOKUP_TABLE for row in cursor }
so in general given some _container with some kind of elements and a function _value which for a given element returns the value that you want to add to this key in the dictionary:
{ _key : _value(_key) for _key in _container }
What you're using is called a list comprehension. They're pretty awesome ;)
They have a cousin called a generator expression that works like a list comprehension but instead of building the list all at once, they generate one item at a time. Hence the name generator. You can even build functions that are generators - there are plenty of questions and sites to cover that info, though.
You can do one of two things:
x = dict(((row.SITE_NAME, row.LOOKUP_TABLE) for row in cursor))
Or, if you have a sufficiently new version of Python, there is something called a dictionary comprehension - which works like a list comprehension, but produces a dictionary instead.
x = {row.SITE_NAME : row.LOOKUP_TABLE for row in cursor}
You can do it like this:
x = dict((row.SITE_NAME, row.LOOKUP_TABLE) for row in cursor)

Categories