How to recognize a list to smooth a python list?

I recently looked for a way to smooth out a nested python list, for example: [[1,2,3], [4,5,6]]: [1,2,3,4,5, 6].

Stackoverflow was always helpful, and I found a post with this ingenious list comprehension:

l = [[1,2,3],[4,5,6]] flattened_l = [item for sublist in l for item in sublist] 

I thought I understood how lists work, but apparently I didn't get a clue. What bothers me the most is that in addition to understanding the above, it also works (although it does not give the same result):

 exactly_the_same_as_l = [item for item in sublist for sublist in l] 

Can someone explain how python interprets these things? Based on the second composition, I would expect the python to interpret it back, but apparently this is not always the case. If so, the first understanding should cause an error because "subscriptions" do not exist. My mind is completely perverted, help!

+6
source share
4 answers

Let’s take a look at your understanding of the list, but first we’ll start by understanding the list and the easiest way.

 l = [1,2,3,4,5] print [x for x in l] # prints [1, 2, 3, 4, 5] 

You can look at this in the same way as you can look at a loop built like this:

 for x in l: print x 

Now let's look at another:

 l = [1,2,3,4,5] a = [x for x in l if x % 2 == 0] print a # prints [2,4] 

This is exactly the same as this:

 a = [] l = [1,2,3,4,5] for x in l: if x % 2 == 0: a.append(x) print a # prints [2,4] 

Now consider the examples you provided.

 l = [[1,2,3],[4,5,6]] flattened_l = [item for sublist in l for item in sublist] print flattened_l # prints [1,2,3,4,5,6] 

To understand the list, start from the farthest left for the loop and work your way up. In this case, the variable element will be added. It will produce this equivalent:

 l = [[1,2,3],[4,5,6]] flattened_l = [] for sublist in l: for item in sublist: flattened_l.append(item) 

Now for the last

 exactly_the_same_as_l = [item for item in sublist for sublist in l] 

Using the same knowledge, we can create a for loop and see how it looks.

 for item in sublist: for sublist in l: exactly_the_same_as_l.append(item) 

Now, the only reason this works is because when creating flattened_l she also created a sublist . This is a summary reason why this did not cause an error. If you run this without defining flattened_l, you will get a NameError

+4
source

For loops are evaluated from left to right. Any list comprehension can be rewritten as a for loop as follows:

 l = [[1,2,3],[4,5,6]] flattened_l = [] for sublist in l: for item in sublist: flattened_l.append(item) 

The above code is the correct code to align the list, regardless of whether you decide to write it briefly as an understanding of the list or in this extended version.

The second understanding of the list you wrote will raise the value of NameError since 'sublist' is not yet defined. You can see this by writing a list comprehension as a for loop:

 l = [[1,2,3],[4,5,6]] flattened_l = [] for item in sublist: for sublist in l: flattened_l.append(item) 

The only reason you didn’t notice an error while running the code was because you previously defined subscriptions when implementing the first understanding of the list.

For more information, you can check out Guido's Understanding Listing Tutorial .

+2
source

For a lazy developer who wants a quick answer:

 >>> a = [[1,2], [3,4]] >>> [i for g in a for i in g] [1, 2, 3, 4] 
+1
source

Note, of course, that the kind of understanding will only “smooth out” the list of lists (or the list of other iterations). Also, if you pass it a list of strings, you will “smooth” it into a list of characters.

To summarize this in a meaningful way, you first want to be able to clearly distinguish between strings (or bytearrays) and other types of sequences (or other Iterables). So let's start with a simple function:

 import collections def non_str_seq(p): '''p is putatively a sequence and not a string nor bytearray''' return isinstance(p, collections.Iterable) and not (isinstance(p, str) or isinstance(p, bytearray)) 

Using this, we can build a recursive function to smooth out any

 def flatten(s): '''Recursively flatten any sequence of objects ''' results = list() if non_str_seq(s): for each in s: results.extend(flatten(each)) else: results.append(s) return results 

There are probably more elegant ways to do this. But this works for all the built-in Python types that I know of. Simple objects (numbers, strings, None, True, False instances are returned to the list. Dictionaries are returned as keylists (in a hash order).

0
source

Source: https://habr.com/ru/post/974850/


All Articles