# Flatten List in Python

In Python, you can flatten a nested list (a list that contains other lists) into a single list using a recursive function or using built-in libraries such as itertools.

Here’s an example of a recursive function that flattens a list:

```def flatten_list(nested_list):
flat_list = []
for item in nested_list:
if isinstance(item, list):
flat_list.extend(flatten_list(item))
else:
flat_list.append(item)
return flat_list
```

Here’s an example of using itertools to flatten a list:

```import itertools

nested_list = [[1, 2], [3, 4], [5, 6]]
flat_list = list(itertools.chain(*nested_list))
```

You can also use the `itertools.chain.from_iterable()` method to flatten a list:

```import itertools

nested_list = [[1, 2], [3, 4], [5, 6]]
flat_list = list(itertools.chain.from_iterable(nested_list))
```

All three methods will produce the same result:

```>>> print(flat_list)
[1, 2, 3, 4, 5, 6]
```

### What are the types of Nested Lists?:

In Python, a nested list is a list that contains one or more lists as elements. Nested lists can have various types, depending on the types of their elements. Here are some examples:

1. Homogeneous nested lists: A homogeneous nested list is a list in which all the elements of the sublists are of the same type. For example, a nested list of integers:
```nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
```
1. Heterogeneous nested lists: A heterogeneous nested list is a list in which the sublists can contain elements of different types. For example, a nested list containing both integers and strings:
```nested_list = [[1, 'apple'], [2, 'banana'], [3, 'cherry']]
```
1. Jagged nested lists: A jagged nested list is a list in which the sublists have different lengths. For example:
```nested_list = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
```
1. Empty nested lists: A nested list can also be empty. For example:
```nested_list = [[], [], []]
```

It’s worth noting that nested lists can be nested to any depth. For example:

```nested_list = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
```

In this case, the nested list contains two sublists, each of which contains two sublists of integers.

### Flattening the List of Lists using the Nested for Loops:

You can use nested for loops to flatten a list of lists in Python. Here’s an example code:

```nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

flat_list = []
for sublist in nested_list:
for item in sublist:
flat_list.append(item)

print(flat_list)
```

Output:

```[1, 2, 3, 4, 5, 6, 7, 8, 9]
```

In this code, we start by initializing an empty list called `flat_list`. We then use two nested for loops to iterate over each sublist in the `nested_list` and then iterate over each item in the sublist. Finally, we append each item to the `flat_list`.

The resulting `flat_list` contains all the items from the original nested list in a flattened form. You can use this code to flatten a list of lists of any size and complexity.

### Flattening the Nested List using a List Comprehension:

You can use a list comprehension to flatten a nested list in Python. Here’s an example code:

```nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

flat_list = [item for sublist in nested_list for item in sublist]

print(flat_list)
```

Output:

```[1, 2, 3, 4, 5, 6, 7, 8, 9]
```

In this code, we use a single list comprehension to flatten the `nested_list`. The list comprehension contains two loops: an outer loop that iterates over each sublist in the `nested_list`, and an inner loop that iterates over each item in the sublist. The resulting `flat_list` contains all the items from the original nested list in a flattened form.

This approach is more concise than using nested for loops, and it can also be faster for larger lists. However, it may be less readable for people who are not familiar with list comprehensions.

### Flattening the List of Lists using the Recursive method:

You can use a recursive function to flatten a nested list in Python. Here’s an example code:

```def flatten_list(nested_list):
flat_list = []
for item in nested_list:
if isinstance(item, list):
flat_list.extend(flatten_list(item))
else:
flat_list.append(item)
return flat_list

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

flat_list = flatten_list(nested_list)

print(flat_list)
```

Output:

```[1, 2, 3, 4, 5, 6, 7, 8, 9]
```

In this code, we define a recursive function called `flatten_list` that takes a nested list as its input and returns a flattened list. The function first initializes an empty list called `flat_list`. It then iterates over each item in the `nested_list`. If an item is a list, the function recursively calls itself with the sublist as the input and extends the `flat_list` with the resulting flattened list. If an item is not a list, the function simply appends the item to the `flat_list`. Finally, the function returns the `flat_list`.

To use the function, we simply call it with the `nested_list` as its input and assign the returned flattened list to `flat_list`.

This approach is very powerful because it can handle nested lists of any depth and complexity. However, it may be slower and less efficient than other methods for very large lists due to the recursive function calls.

### Utilizing Libraries of Python:

Python provides several built-in libraries that can be used to flatten a nested list or perform other operations on lists. Here are some examples:

1. `itertools.chain`: This library provides the `chain` function, which can be used to flatten a nested list of any depth. Here’s an example code:
```import itertools

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

flat_list = list(itertools.chain(*nested_list))

print(flat_list)
```

Output:

```[1, 2, 3, 4, 5, 6, 7, 8, 9]
```

In this code, we first import the `itertools` library. We then use the `chain` function to flatten the `nested_list`. The `*` operator is used to unpack the sublists in the `nested_list` and pass them as separate arguments to the `chain` function. Finally, we convert the result to a list using the `list` function.

1. `numpy`: This library provides the `flatten` function, which can be used to flatten a nested list of any depth. Here’s an example code:
```import numpy as np

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

flat_list = np.array(nested_list).flatten().tolist()

print(flat_list)
```

Output:

```[1, 2, 3, 4, 5, 6, 7, 8, 9]
```

This creates a one-dimensional NumPy array with the values 1, 2, and 3.

### Utilizing Core Functions:

Python has many built-in functions that you can use for various tasks. Here are some examples of commonly used Python core functions:

1. `print()`: The `print()` function is used to print output to the console. You can pass one or more arguments to the function, which will be printed as strings. For example, `print("Hello, World!")` will print the string “Hello, World!” to the console.
2. `len()`: The `len()` function is used to get the length of a sequence, such as a string, list, or tuple. For example, `len("hello")` will return 5.
3. `range()`: The `range()` function is used to create a sequence of numbers. You can pass one, two, or three arguments to the function to specify the start, stop, and step values. For example, `range(1, 10, 2)` will return the sequence `[1, 3, 5, 7, 9]`.
4. `input()`: The `input()` function is used to get user input from the console. When called, it will prompt the user to enter a value. The value entered by the user will be returned as a string. For example, `name = input("What is your name?")` will prompt the user to enter their name and assign the entered value to the variable `name`.
5. `sorted()`: The `sorted()` function is used to sort a sequence, such as a list or tuple. It takes one argument, the sequence to be sorted, and returns a new sorted sequence. For example, `sorted([3, 1, 4, 1, 5, 9, 2, 6, 5])` will return the list `[1, 1, 2, 3, 4, 5, 5, 6, 9]`.
6. `max()` and `min()`: The `max()` and `min()` functions are used to get the maximum and minimum values from a sequence, respectively. They take one argument, the sequence to be analyzed, and return the maximum or minimum value, respectively. For example, `max([3, 1, 4, 1, 5, 9, 2, 6, 5])` will return 9, and `min([3, 1, 4, 1, 5, 9, 2, 6, 5])` will return 1.

These are just a few examples of the many built-in functions in Python. To use a function, simply call it with the appropriate arguments. For example, `print("Hello, World!")` will call the `print()` function and pass the string “Hello, World!” as an argument.