简体   繁体   中英

python list comprehension: return a list of strings instead of a list of lists

For a homework assignment, we were required to create a function that took in two inputs (list and a string) and that returned a list. I would like to write this function using list comprehension, but have been running into an annoying issue. Here is he original function I would like to re-write:

index = [['keyword1', ['url1', 'url2', 'url3']], ['keyword2', ['url4', 'url5']]...]

def lookup(index, keyword):
    result = []
    for entry in index:
        if entry[0] == keyword:
            result += entry[1]
    return result

These were my attempts at using list comprehension:

def lookup(index, keyword):
    return [entry[1] for entry in index if entry[0] == keyword]

def lookup(index, keyword):
    return [ulist for key, ulist in index if i == keyword]

and finally...

def lookup(index, keyword):
    return [j for j in (entry[1] for entry in index if entry[0] == keyword)]

The problem here is that it returns the desired urls in a list inside of a list, like so:

[['url1', 'url2', 'url3']]

instead of the desired format of:

['url1', 'url2', 'url3']

I thought of just doing something like this (adding [0] to the end of the return statement so it gives me the inner list):

def lookup(index, keyword):
        return [j for j in (entry[1] for entry in index if entry[0] == keyword)][0]

But it just doesn't seem like the right way. Am I trying to use list comprehension unnecessarily (my understanding was that this situation was well suited for list comprehension)? Any suggestions?

This would be the most straightforward way:

def lookup(index,keyword):
    return [x for entry in index if entry[0]==keyword for x in entry[1]]

The nested list comprehension syntax isn't what you might initially expect. The key is to realize that the use of the two for loops is not two separate list comprehensions, but a single list comprehension with nested loops. That is actually why it works. It is like you were writing

for entry in index:
  if entry[0]==keyword:
    for x in entry[1]:
      yield x

The order in list comprehensions is the same as in regular loops, except for the yielded value, which comes first.

You should use a dictionary instead, because its API is more naturally suited to talking (and quickly processing) things related to maps.

keywordToUrl = {keyword1:(url1,url2,url3), keyword2:(url4,url5), ...}
keywordToUrl[keyword]
def lookup(index, keyword):
    return sum((entry[1] for entry in index if entry[0] == keyword), [])

Example:

>>> index = [['keyword1', ['url1', 'url2', 'url3']], ['keyword2', ['url4', 'url5']]]
>>> lookup(index, 'keyword1')
['url1', 'url2', 'url3']
def lookup(index,keyword):
    return [j for j in (entry[1] for entry in index if entry[0] == keyword)]

The problem is that you're returning something inside brackets, hence your value is being returned inside a list, remove the brackets and problem solved.

This would be the correct code:

def lookup(index,keyword):
    return j for j in (entry[1] for entry in index if entry[0] == keyword)

I apologize for the previous inconvenience. I already tested your code, if you take a look at the index list your values are not uniform:

index = [['keyword1', ('url1', 'url2', 'url3')], ['keyword2', ['url4', 'url5']]...]

here index[0][1] has a tuple and index[1][1] has a list.

If you make all the second values of the lists inside index, a tuple here's what happens:

Here's the same code as yours:

index = [["keyword1", ("url1", "url2", "url3")], ["keyword2", ("url4", "url5")]]
def lookup(index, keyword):
    return [entry[1] for entry in index if entry[0] == keyword]

print lookup(index,"keyword1")

And this is the output:

[('url1', 'url2', 'url3')]

You can notice that this isn't a list inside a list, cause all the values in index[i][1] are tuples now.

if you want this output:

['url1', 'url2', 'url3']

You'll need to convert that tuple into a list, which Python does not automatically for you. As described in the official documentation, a list comprehension always returns a list, thats why the tuple is inside a list.

http://www.python.org/dev/peps/pep-0202/

Let's take this example: when I give a letter and a list the return function will give the names that are there in the list starting with that letter.

def abc(letter , nameslist):
    return [name for name in nameslist if name[0].lower() == letter.lower() ]


nameslist = ["Sou", "Soudipta", "Gini", "Protijayi", "Gina"]

print( abc("P",nameslist) )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM