2

Say I have:

list=[('mike', 22.0), ('john', 33.0)]

I want to print a list of just the numbers, smallest to largest. I tried doing this:

for s in list:
    print(sorted(s[1]))

But it said 'int object is not iterable'?

If i do this, it works ( output is: [22,33])

print (sorted(s[1] for s in list))

How does the 2nd one work and what's the difference between the 1st and 2nd attempt? Hard time understanding the list comprehension technique.

BTW, the final goal is to print the NAME of the person will the lowest mark. But I'm trying to understand this part first before I associate the name with the mark. Dict would make it so much easier to assign key-values though

9
  • Type in s[1] and see what you get. Then type in [s[1] for s in list] and see what you get. Then see if it makes more sense. Commented Oct 10, 2015 at 0:46
  • Why don't use a dict here? Commented Oct 10, 2015 at 0:49
  • Don't name your list list, it will override the list function in python. Commented Oct 10, 2015 at 0:49
  • @RobertB How do i print just s[1] without the for s in list... s is not defined Commented Oct 10, 2015 at 0:49
  • @KevinGuan I'm trying to learn list comprehension, Dict would be easier though =p Commented Oct 10, 2015 at 0:51

2 Answers 2

2

When you do:

for s in list:
    print(sorted(s[1]))

You're trying to sort an int. The sorted function requires an iterable (for example, a list). Hence your error. This is noticeable since:

for s in list:
    print(s[1])

prints:

22.0
33.0

On the other hand, when you do: Sorted(s[1] for s in myList), you're sorting a list (actually you're sorting a generator, but there's a somewhat fine line). Try:

newList = [s[1] for s in myList]
newList

and you'll see that you're essentially sorting a list. Sorting a list makes sense, but sorting a single number doesn't. Sorted is a function that returns a sorted list. To illustrate the difference between generators and iterables (like lists, tuples and dicts), compare the last snippet to the below:

newGenerator = (s[1] for s in myList)
print(newGenerator) #probably won't give what you ever need
for item in newGenerator:
    print item  #this will iterate through the items in the generator and print them

I had assumed you wanted the group sorted, but someone else answered that already and got downvoted so I didn't add it. Here is how you would do that:

myList.sort(key = lambda x: x[1])

Then:

myList[0][0]

Will be the name of the lowest person.

In this case, sort is a method, which operates on myList and changes it. If you pass it the key = lambda x: x[1] argument, it will sort the list based on the position 1. So, if your number was in a different position in your tuples you would use a different number there. lambda is just a way to make a function on the fly, in this case the function just grabs the 1 element (second element).

Sign up to request clarification or add additional context in comments.

13 Comments

So what would be another way to sort the numbers into a list , smallest to biggest ( apart from the list comprehension i did).
Actually I'm sorry, your way is the way that I would recommend doing it: sorted(s[1] for s in myList) but I would again recommend using myList vs list, since list converts things to lists in Python :)
K i won't use list next time. But for the sake of this example, I still don't get how the 2nd way works and 1st one doesn't...
Because you can't sort a number :) When you do for s in list you are looking at each item in the list on each iteration of the for loop. At that point, s will look either like ('john', 33.0) or ('mike', 22.0). So, on the first iteration, s = ('john', 33.0), and s[1] = 33.0. Finally, sorted(33) doesn't make sense, because it's just a number.
Well, sorted is really just a function. So, when you do newList = sorted(s[1] for s in myList) the sorted function does most of the work, and returns a sorted list. sorted can take a generator, or an iterable though. A generator can be thought of as an expression that produces items. Whereas an iterable already has the items. sorted(myIterable) will work, and so will sorted(myGenerator). In your case, you pass a generator to sorted, but if you play with the sorted function more, (for instance, try print sorted([3,2,1])), you'll see it works on generators and iterables
|
2

Because a list comprehension will give a generator here, see:

>>> Mylist=[('john', 33.0),('mike', 22.0)]
>>> print(s[1] for s in Mylist)
<generator object <genexpr> at 0x7fd4a005e0f8>

And however, sorted() can be use on an iterable like list or generator, and then convert it to a list.

For example, range() will give a generator on Python 3(if you're using Python 2, use xrange() instead):

>>> a = range(20)
>>> sorted(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

And about why does this list comprehension give a generator, I think you forgot []:

>>> Mylist=[('john', 33.0),('mike', 22.0)]
>>> print(sorted([s[1] for s in Mylist]))
[22.0, 33.0]
>>> print(sorted(s[1] for s in Mylist))
[22.0, 33.0]
>>> print([s[1] for s in Mylist])
[33.0, 22.0]
>>> print(s[1] for s in Mylist)
<generator object <genexpr> at 0x7f8ab881c6d0>
>>> 

By the way, about your code without list comprehension:

>>> Mylist=[('john', 33.0),('mike', 22.0)]
>>> l = []

>>> for s in sorted(Mylist, key=lambda x:x[1]):
...     l.append(s[1])

>>> print(l)
[22.0, 33.0]

5 Comments

why does that generator error thing come? What does it mean?
@Angular That's not an error, just means that's a generator. And what is generator please see the document
Actually in python2 range gives a list but maybe you're using python3.
xrange produces a generator in python2.
@rofls Thanks, I'm really using Python 3 and however I think OP is also using Python 3 :P

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.