## Slicing

We already saw how you can access items in a list using the `list[index]` syntax. This is the simplest case: it gives you a single item. The more general form of the syntax allows you to extract a contiguous subset of the list.

You can specify the index (starting at 0, remember) of the first item (i.e. inclusive), and the index of the item one past the last one you want (i.e. exclusive). For example `l[0:len(l)]` will give you the entire list.

```l = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
l
#'d'
l[3:6]
#['d', 'e', 'f']
l[0:len(l)]
#['a', 'b', 'c', 'd', 'e', 'f', 'g']```

If you are interested in items from the first or last of the list, it can be simplified to omit the `0` or `len(l)`:

```l[:4]
#['a', 'b', 'c', 'd']
l[4:]
#['e', 'f', 'g']```

## Filtering

The `filter` function takes a predicate (i.e. a function that returns a boolean value) and a list. `filter` returns a filter object that generates a list that contains only those elements from the original list for which the predicate returns `True`. Filter predicates can either be a reference to a named function or, quite often, a lambda.

Say you want to pick out only the numbers in a list that are multiples of 3. If `a` is your original list of numbers, say the result of `range(20)`:

```a = range(20)
list(filter(lambda x: x % 3 == 0, a))
#[0, 3, 6, 9, 12, 15, 18]```

Notice the need to use `list` to convert the filter object to a list.

## Mapping

Another common thing to do with lists is to perform some operation on each item, accumulating the results into a new list. The `map` function does this. It takes a function (which is often a lambda)  and the original list. Similar to `filter`, `map` returns a map object.

Let's take the same list `a`, and generate a list of the squares of its contents.

```list(map(lambda x: x**2, a))
#[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361]```

`map` isn't limited to processing a single list; you can pass it any number of lists, with the restriction that the function has to have that number of parameters.

```list(map(lambda x, y: x + y, [0,1,2,3], [4,5,6,7]))
#[4, 6, 8, 10]
```

We can combine `map` with `filter` to process a subset of a list. Let's get the squares of the multiple of 3:

```list(map(lambda x: x**2, filter(lambda x: x % 3 == 0, a)))
#[0, 9, 36, 81, 144, 225, 324]```

While this works, it can be a bit cumbersome at times. Thankfully Python provides a better alternative, which we will examine shortly.

## Reducing

The third function we're going to look at is `reduce`. It's different than `filter` and `map` in that it doesn't result in a sequence of values. Instead it takes a list, a function, and an optional initial value and uses them to compute a single value. It, in essence, reduces the list to a single value.

Unlike `filter` and `map`, `reduce` isn't a built-in; it's in the `functools` module. There are plenty of other fun, useful things in that module but we won't be looking at those now. This module isn't included with CircuitPython, but it is with MicroPython. You can find it at https://github.com/micropython/micropython-lib. To use it with CircuitPython, copy micropython-lib/functools/functools.py (either from a clone of the repository or just the single downloaded file) to the CIRCUITPY drive. Once it's there you'll need to import it:

`from functools import reduce`

`reduce` is sometimes confusing at first, but it's actually quite simple. The function you pass it takes two parameters; let's call them `accumulator` and `x`. This function is called for items of the list (in order), that's the second (`x`) argument. The first argument (`accumulator`) is the result from the previous time the function was called.

The first time through is a little different. If the optional third argument is supplied to `reduce`, it is used as the result of the previous call (as mentioned above). If it's omitted, the first value from the list is used instead.

Some examples should illustrate it:

`reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])`

this is equivalent to:

`((((1+2)+3)+4)+5)`

`reduce(lambda x, y: x+y, [1, 2, 3, 4, 5], 10)`

it would be the same as:

`(((((10+1)+2)+3)+4)+5)`

We can give it a try and see:

```reduce(lambda x,y:x+y,[1,2,3,4,5])
#15
reduce(lambda x,y:x+y,[1,2,3,4,5], 10)
#25```

Note: the type of the result of `reduce` will be the type of the initial value, either the one supplied or the first item in the list.

Of course, like `filter` and `map`, you don't need a lambda. You can use the name of a function if there's one that does exactly what you want.  Since Python lambdas are limited to a single expression, you might sometimes need to write a function just to be used for one of these functions.

```def prepend(l, x):
l.insert(0, x)
return l

reduce(prepend, ['a', 'b', 'c'], [])
# returns ['c', 'b', 'a']```

We can't use a lambda here because `insert` doesn't return the list. We need to do that as a second step, which we can't do in a lambda. Also, we need to provide the empty list as the initial accumulator value so that

1.  the result will be a list, and
2.  there's something to insert the first item into.

This guide was first published on Oct 11, 2018. It was last updated on Oct 11, 2018.