Double list Comprehension with range - python

I have a list in Python which I'm trying to print the first five elements out of it using list comprehension.
I understand that this has to be done using double list comprehensions. I have the following at the moment:
print [[x[i] for x in mylist] for i in range(0,5)]
This throws the following error: IndexError: tuple index out of range.
When I print each one separately, it works out fine. I do print mylist[0], print mylist[1] etc...
What is the issue here? I have a feeling that my entire double comprehension is not right. Now here's what I'm thinking:
[x for x in range(0,5)]
This creates a list of x's for each x in range(0,5). Since this is my index, I nested another list comprehension statement before that as above to do that over my specific list.
Any help is appreciated. Thanks!

mylist[:5] gives the first 5 elements of mylist. (If mylist has fewer than 5 elements in it, then mylist[:5] will return a list of length len(mylist).) Using a list comprehension here would be overkill.

Provided myList contains at least 5 elements, and you really want to use list comprehension, try this:
[print (mylist[i]) for i in range (0, 5)]

unutbu's is the best solution. Performing it using list comprehensions, you'd want
[mylist[i] for i in range(5)]

As for why you are getting the error, if myList is a list of tuples, look at it like this:
myList = [(0, 1), (1, 2), (2, 3)]
result = []
for i in range(5):
sub_result = []
# Here x will be (0, 1), etc.
for x in myList:
# Here you are referencing the ith element of your tuple
# If your tuple doesn't contain that many elements, you get the error
sub_result.append(x[i])
Therefore it is accessing your tuple and not your list. The other solutions all show how to correct this, so definitely vote for one them - this will hopefully just help figure out why it is causing an error :)

print [mylist[j] for j in [ i for i in range(5)]]
Although #unutbu's approach is much more readable.

You are trying to access indexes that out of range.
It means that your x tuple has length < 5.
It happens for data like [[1,2,3],[4,5,6]..]
x here would be [1,2,3], then [4,5,6] etc
when you try x[5] - you get Exception

Related

Why is the order of elements in my list mixed up when I pass them through a generator?

I'm trying to convert elements in a nested list to strings before joining them with " | " using the join operator. However, the order of the last 2 elements in my list keeps getting reversed when I get the output from the generator
I've tried running the program multiple times but it always comes out reversed.
numbers = [[1,2,3],[4,5,6],[7,8,9]]
for i in numbers:
print(i)
num = {str(x) for x in i}
print(num)
Expected Output is [1,2,3].
Actual output is [1,3,2] consistently.
Any help with this would be much appreciated! :)
This isn't a generator, it's a set comprehension. The result is a set, and sets are unordered.
Use a list comprehension:
num = [str(x) for x in i]

getting last element of a list of unknown size using slices

Let's say I have a list of unknown size, then I can access the last element using:
>>> l = list(range(10))
>>> l[-1]
9
However, is there any way to do this via a slice object like
>>> s = slice(-1, 10)
>>> l[s]
[9]
without knowing the length of my list?
Edit:
I simplified my Question a bit. I am fine with getting a list back, since I am iterating over the sublist later. I just needed a way of getting the last item of list besides being able to get every second element and so on ...
Yes, just use None as the end argument:
In [53]: l[slice(-1, None)]
Out[53]: [9]
This will of course produce a list [9], rather than the 9 in your question, because slicing a list always produces a sublist rather than a bare element.
If your objective is to pass arguments which you can use to index a list, you can use operator.itemgetter:
from operator import itemgetter
L = range(10)
itemgetter(-1)(L) # 9
In my opinion, for this specific task, itemgetter is cleaner than extracting a list via a slice, then extracting the only element of the list.
Note also that this works on a wider range of objects than just lists, e.g. with range as above.
If you were to access the last element of the list:
n = int(input())
user_input = [int(input) for i in range(n)]
last_element = user_input[-1]
Here we have used negative indices concept in lists.

Put average of nested list values into new list

I have the following list:
x = [(27.3703703703704, 2.5679012345679, 5.67901234567901,
6.97530864197531, 1.90123456790123, 0.740740740740741,
0.440136054421769, 0.867718446601942),
(25.2608695652174, 1.73913043478261, 6.07246376811594,
7.3768115942029, 1.57971014492754, 0.710144927536232,
0.4875, 0.710227272727273)]
I'm looking for a way to get the average of each of the lists nested within the main list, and create a new list of the averages. So in the case of the above list, the output would be something like:
[[26.315],[2.145],[5.87],etc...]
I would like to apply this formula regardless of the amount of lists nested within the main list.
I assume your list of tuples of one-element lists is looking for the sum of each unpacked element inside the tuple, and a list of those options. If that's not what you're looking for, this won't work.
result = [sum([sublst[0] for sublst in tup])/len(tup) for tup in x]
EDIT to match changed question
result = [sum(tup)/len(tup) for tup in x]
EDIT to match your even-further changed question
result = [[sum(tup)/len(tup)] for tup in x]
An easy way to acheive this is:
means = [] # Defines a new empty list
for sublist in x: # iterates over the tuples in your list
means.append([sum(sublist)/len(sublist)]) # Put the mean of the sublist in the means list
This will work no matter how many sublists are in your list.
I would advise you read a bit on list comprehensions:
https://docs.python.org/2/tutorial/datastructures.html
It looks like you're looking for the zip function:
[sum(l)/len(l) for l in zip(*x)]
zip combines a collection of tuples or lists pairwise, which looks like what you want for your averages. then you just use sum()/len() to compute the average of each pair.
*x notation means pass the list as though it were individual arguments, i.e. as if you called: zip(x[0], x[1], ..., x[len(x)-1])
r = [[sum(i)/len(i)] for i in x]

Understanding "ValueError: need more than 1 value to unpack" w/without enumerate()

I've been searching around for a succinct explanation of what's going on "under the hood" for the following, but no luck so far.
Why, when you try the following:
mylist = ["a","b","c","d"]
for index, item in mylist:
print item
I get this error:
ValueError: need more than 1 value to unpack
But when I try:
for item in mylist:
print item
This is returned:
a
b
c
d
If indexes are a part of the structure of a list, why can't I print them out along with the items?
I understand the solution to this is to use enumerate(), but I'm curious about why iterating through lists (without using enumerate()) works this way and returns that ValueError.
I think what I'm not understanding is: if you can find items in a list by using their index (such as the case with item = L[index] ) — doesn't that mean that one some level, indexes are an inherent part of a list as a data structure? Or is item = L[index] really just a way to get Python to count the items in a list using indexes (starting at 0 obviously)? In other words, item = L[index] is "applying" indexes to the items in the list, starting at 0.
If indexes are a part of the structure of a list...
Except they aren't. Not when you iterate over the list. The indexing becomes a matter of time/occurrence, and they are no longer associated with the elements themselves.
If you were to actually print out the result of the enumerate() function as a list:
print(list(enumerate(["a","b","c","d"])))
You would see this:
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
Therefore, if you wanted to print the index and item at that index using enumerate(), you could technically write this:
for pair in enumerate(mylist):
print pair[0], pair[1]
However, that's not the best (i.e. Pythonic) way of doing things. Python lets you write the above much more nicely like so:
for index, item in enumerate(mylist):
print index, item
This works because when you use the index, item syntax, you are telling Python to "unpack" each pair in that list by treating the components of each pair separately.
For more on how this tuple unpacking magic works, see:
Tuple unpacking in for loops

How to add lower function to this code

I want to print my output in lowercase, but I am not getting the correct results. Here's my code. Please help!
import csv
mags = csv.reader(open("mags.csv","rU"))
for row in mags:
print [row[index] for index in (1, 0)]
print [item.lower( ) for item in row]
List comprehension can be nested, like so
print [item.lower() for item in [row[index] for index in (1, 0)]]
Don't have an interpreter handy to test this, tho.
You can nest the two comprehensions like this:
print [item.lower() for item in [row[index] for index in (1, 0)]]
That way you'll use the data from the first comprehension (the second and first item of the row in this order) as input for the second one (lowercase everything).
You can also slice the row instead of using a comprehension for the first one:
print [item.lower() for item in row[::-1][-2:]] # Slicing in 2 steps: [::-1] reverses the list and [-2:] returns the last two items of the reversed list
or (Shorter, but reversed indices slicing doesn't work as you'd think)
print [item.lower() for item in row[1::-1] # Same thing, but it helps to break these things up into steps
Are you sure that the row is a list of strings here ?
I see correct output :
>>> row = [ "alpA", "bETA","gammA" ]
>>> print [item.lower( ) for item in row]
['alpa', 'beta', 'gamma']
>>>

Categories

Resources