Python 3 - List

Updated: 2018-12-09
>>> arr = ['A', 'B', 'C']
>>> arr.index('B')
1
>>> arr.index('C')
2
>>> arr.index('D')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.index(x): x not in list

A simple list a

>>> a = [1, 2, 3]

replicate the elements of a 3 times

>>> b = a * 3
>>> b
[1, 2, 3, 1, 2, 3, 1, 2, 3]

replicate a as a list 3 times

>>> c = [a] * 3
>>> c
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]

Modify a's element:

>>> a[0] = 0

b will not be changed

>>> b
[1, 2, 3, 1, 2, 3, 1, 2, 3]

However c will be impacted

>>> c
[[0, 2, 3], [0, 2, 3], [0, 2, 3]]

All 3 elements are pointing to the same object

>>> a.__repr__
<method-wrapper '__repr__' of list object at 0x10f8fc888>

>>> c[0].__repr__
<method-wrapper '__repr__' of list object at 0x10f8fc888>

>>> c[1].__repr__
<method-wrapper '__repr__' of list object at 0x10f8fc888>

>>> c[2].__repr__
<method-wrapper '__repr__' of list object at 0x10f8fc888>

However b is making a copy of a's content(address is different):

>>> a[0].__repr__
<method-wrapper '__repr__' of int object at 0x10f414850>

>>> b[0].__repr__
<method-wrapper '__repr__' of int object at 0x10f414870>

Another way to check:

>>> id(a)
4556048520

>>> id(c[0])
4556048520

>>> id(b)
4556049096

>>> id(c)
4556049032

Copy of the list:

>>> d = c
>>> d
[[0, 2, 3], [0, 2, 3], [0, 2, 3]]

>>> e = c[:]
>>> e
[[0, 2, 3], [0, 2, 3], [0, 2, 3]]

>>> d[0] = 'foo'
>>> d
['foo', [0, 2, 3], [0, 2, 3]]
>>> c
['foo', [0, 2, 3], [0, 2, 3]]
>>> e
[[0, 2, 3], [0, 2, 3], [0, 2, 3]]

d simply points to c, while e is a copy of c

GroupBy

The Array must be sorted

import itertools
>>> a = [1,2,3,4,5,1,2,3,4]
>>> [(x, list(y)) for (x,y) in itertools.groupby(sorted(a))]
[(1, [1, 1]), (2, [2, 2]), (3, [3, 3]), (4, [4, 4]), (5, [5])]

Join As String

Join a string array

>>> ','.join(['1','2','3'])
'1,2,3'

Join a numeric array

Call join directly will generate a TypeError

>>> ','.join([1,2,3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sequence item 0: expected str instance, int found

Convert numbers to string first, e.g. use map()

>>> ','.join(map(str, [1,2,3]))
'1,2,3'

Example

>>> b = [[None] * 3 for i in range(3)]

>>> b
[[None, None, None], [None, None, None], [None, None, None]]
>>> b[2][1]=1

>>> b
[[None, None, None], [None, None, None], [None, 1, None]]

>>> c = [[None] * 3] * 3

>>> c

[[None, None, None], [None, None, None], [None, None, None]]

>>> c[2][1]=1

>>> c
[[None, 1, None], [None, 1, None], [None, 1, None]]

Remove Duplicates

A more pragmatic way to remove adjacent duplicates is like this:

>>> row = [k for k, g in itertools.groupby(row)]
>>> row
[(115, 115, 115, 255), (109, 109, 109, 255), (97, 97, 97, 255), ... (95, 82, 47, 255), (97, 83, 46, 255), (99, 85, 46, 255)]

itertools.groupby only work on sorted lists, which means it will only group the adjacent duplicates; then the k, g represents the key and group of tuples in the grouped result, but we only care about the keys.

[(k, len(list(g))) for k, g in itertools.groupby(sorted(a))]