I want to write a list comprehension that will have print an element out of an array every other element. How do I do so?
for item in results:
record = extract_record(item)
if record:
records.append(record)
in Python 3.8 or later you could make use of the assignment expression and do something like
records = [record for item in results if (record := extract_record(item))]
This avoids having to extract the record twice.
The list comprehension equivalent of the above will be:
records = [extract_record(item) for item in results if extract_record(item)]
Note that extract_record() is needed twice and hence not so useful.
Related
I am having a hard time interpreting nested iteration inside a list comprehension. Below code
movie = []
genre = []
for movie_ids in ratings["movie_id"].values:
movie.append(movie_ids)
genre.append([x for movie_id in movie_ids for x in genres_dict[movie_id]])
If I print genre[0] suppose I see a result [a,b,c]
My understanding from this and many others on the internet was that I can replace the line
genre.append([x for movie_id in movie_ids for x in genres_dict[movie_id]])
With
for movie_id in movie_ids:
if movie_id in genres_dict:
genre.append(genres_dict[movie_id])
But that gives a different result when I print genre[0]
What am I missing?
Please suggest
With the list comprehension, you are also iterating over the contents of genres_dict[movie_id]. This code would not quite translate into the for loop you provided, but instead into
for movie_id in movie_ids:
for x in genres_dict[movie_id]
genre.append(x)
I have omitted the if statement because, although it is not a bad idea to test whether the key exists, the nested iteration does not perform this test either. Nested iteration essentially performs the for loops you provide, nested, from the left to the right, and then appends the result of the expression.
Furthermore, appending the result of a list comprehension does not add every element of the list comprehension individually, but instead the entire list as one element. So the code actually performs
list_out = []
for movie_id in movie_ids:
for x in genres_dict[movie_id]
list_out.append(x)
genre.append(list_out)
If you want to add all of the elements of the list comprehension, you should instead use list.extend, which takes an iterable as an argument and adds every element to the list. In your original code this would be
genre.extend([x for movie_id in movie_ids for x in genres_dict[movie_id]]).
The list comprehension is actually flattening the array for you as it iterates over the inner content also.
The equivalent code block would be this. Notice the extend vs append.
for movie_id in movie_ids:
if movie_id in genres_dict:
genre.extend(genres_dict[movie_id])
The extend takes care of iterating over each item and adding it to the genre list. See docs for append vs extend.
https://docs.python.org/3/tutorial/datastructures.html
Generally, a list comprehension follows a following pattern:
my_list = [record for record in records_set]
It could be extended to, for example, the following expression, if record is a dictionary:
my_list = [(record['attribute_a'],record['attribute_b']) for record in records_set]
What if I want the list comprehension to take a list of attributes I want to extract from a record as an argument?
Lets say I have a list
attributes_list = ['attribute_a','attribute_b','attribute_c']
As a result of applying it to the list comprehension pattern, I want to get the following list comprehension as a result:
my_list = [(record['attribute_a'],record['attribute_b'],record['attribute_c']) for record in records_set]
How do I do it?
You can do:
my_list = [tuple(record[attr] for attr in attributes_list) for record in records_set]
The easiest thing to do is use operator.itemgetter
from operator import itemgetter
values_from = itemgetter(*attributes_list)
my_list = [values_from(record) for record in record_set]
This makes it easy to skip the list comprehension and use map instead.
my_list = list(map(itemgetter(*attributes_list), record_set))
(As usual, the call to list is necessary in Python 3, not Python 2.)
Im pretty new to Python.
I have a list which looks like the following:
list = [('foo,bar,bash',)]
I grabbed it from and sql table (someone created the most rubbish sql table!), and I cant adjust it. This is literally the only format I can pull it in. I need to chop it up. I can't split it by index:
print list[0]
because that just literally gives me:
[('foo,bar,bash',)]
How can I split this up? I want to split it up and write it into another list.
Thank you.
list = [('foo,bar,bash',)] is a list which contains a tuple with 1 element. You should also use a different variable name instead of list because list is a python built in.
You can split that one element using split:
lst = [('foo,bar,bash',)]
print lst[0][0].split(',')
Output:
['foo', 'bar', 'bash']
If the tuple contains more than one element, you can loop through it:
lst = [('foo,bar,bash','1,2,3')]
for i in lst[0]:
print i.split(',')
With a list that looks something like:
cell_lines = ["LN18_CENTRAL_NERVOUS_SYSTEM","769P_KIDNEY","786O_KIDNEY"]
With my dabbling in regular expressions, I can't figure out a compelling way to search individual strings in a list besides looping through each element and performing the search.
How can I retrieve indices containing "KIDNEY" in an efficient way (since I have a list of length thousands)?
Make a list comprehension:
[line for line in cell_lines if "KIDNEY" in line]
This is O(n) since we check every item in a list to contain KIDNEY.
If you would need to make similar queries like this often, you should probably think about reorganizing your data and have a dictionary grouped by categories like KIDNEY:
{
"KIDNEY": ["769P_KIDNEY","786O_KIDNEY"],
"NERVOUS_SYSTEM": ["LN18_CENTRAL_NERVOUS_SYSTEM"]
}
In this case, every "by category" lookup would take "constant" time.
You can use a set instead of a list since it performs lookups in constant time.
from bisect import bisect_left
def bi_contains(lst, item):
""" efficient `item in lst` for sorted lists """
# if item is larger than the last its not in the list, but the bisect would
# find `len(lst)` as the index to insert, so check that first. Else, if the
# item is in the list then it has to be at index bisect_left(lst, item)
return (item <= lst[-1]) and (lst[bisect_left(lst, item)] == item)
Slightly modifying the above code will give you pretty good efficiency.
Here's a list of the data structures available in Python along with the time complexities.
https://wiki.python.org/moin/TimeComplexity
I've got list of lists, (specifically the results of a results of a SQL query) that I want to add to the end of another list of lists (the results from a previous query/queries). The list comprehension that I think should do this
[results.append(result) for result in currentResults]
doesn't append the rows, but instead adds None where each row should be. However, if I do this with an if statement
for result in currentResults:
results.append(result)
it works perfectly.
Why do these two statements not do the same thing, and is there a way to do this with a list comprehension?
The return value of .append() is None. That return value is what is going into your comprehension.
If the for loop works perfectly, then you should be able to just replace it with
results += list(currentResults)
Or, perhaps you might prefer:
results.extend(currentResults)
A list comprehension would work like:
results += [r for r in currentResults]