Skip to content

Commit

Permalink
Merge pull request #23 from tmck-code/20241128_comparing_lists_or_mat…
Browse files Browse the repository at this point in the history
…rices

20241128 comparing lists or matrices
  • Loading branch information
tmck-code authored Nov 28, 2024
2 parents eb03d7d + ab74bff commit 9845b7e
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ my blog

---

### [20241128 Comparing Lists or Matrices](articles/20241128_comparing_lists_or_matrices/20241128_comparing_lists_or_matrices.md)

> _Functional approaches to compare sequences in Python_
### [20240829 Using JQ with style](articles/20240829_using_jq_with_style/20240829_using_jq_with_style.md)

> _Colour/theme configuration for jq_
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# 20241128 Comparing Lists or Matrices

Recently I needed to compare matrices (or "lists of lists"), counting the number of different items. I challenged myself to
use the standard library instead of numpy.

---

These matrices have 2 differing values:

```python
m1 = [(0,0),
(0,1),]

m2 = [(0,1),
(0,0),]
```

Firstly, it would be easiest (for me) if I somehow transformed each matrix into a single sneuence of numbers.
This can be done using `chain` from the `itertools` standard library tools, which is one of my favourite and probably overused hacks.

```python
from itertools import chain

list(chain.from_iterable(m1))
# [0, 0, 0, 1]

list(chain.from_iterable(m2))
# [0, 1, 0, 0]
```

Using `zip`, we can iterate through both lists and compare each pair of elements:

```python
list(zip(
chain.from_iterable(m1),
chain.from_iterable(m2)
))
# [(0, 0), (0, 1), (0, 0), (1, 0)]
```

Next, we need to compare each pair of elements, and I thought of using the `operator` functions, as there is `ne` which could be used to compare elements.

The documentation for `ne` is:

> `ne(a, b, /)` *Same as a != b.*
I want to avoid using a lambda as it is both icky and slow, e.g.

```python
list(map(
lambda x: x[0]==x[1],
zip(
chain.from_iterable(m1),
chain.from_iterable(m2)
)
))
# [True, False, True, False]
```

I can use `starmap` to take each pair, and pass it to `operator.eq` as `*args` (hence the name "starmap"! very cool 😎)

```python
from itertools import starmap

list(starmap(
operator.ne,
zip(
chain.from_iterable(m1),
chain.from_iterable(m2)
)
))
# [True, False, True, False]
```

And finally, `sum` can be used to count the number of `True`/truthy results

```python
sum(starmap(
operator.ne,
zip(
chain.from_iterable(m1),
chain.from_iterable(m2)
)
))
# 2
```

> *Note: counting identical elements could be done easily by using `operator.eq` instead of `operator.ne`*

0 comments on commit 9845b7e

Please sign in to comment.