Search code examples
pythonstringlistextend

python fixed array of dynamic strings list


I would like to fill iteratively an array of fixed size where each item is a list of strings. For example, let's consider the following strings list:

arr = ['A1', 'C3', 'B2', 'A2', 'C1', 'A3', 'B1', 'C2', 'A4']

I want to obtain the following array of 3 items (no ordering is required):

res = [['A1', 'A2', 'A3', 'A4'],
       ['B2', 'B1'],
       ['C3', 'C1', 'C2']]

I have the following piece of code:

arr = ['A1', 'C3', 'B2', 'A2', 'C1', 'A3', 'B1', 'C2', 'A4']
res = [[]] * 3
for i in range(len(arr)):
    # Calculate index corresponding to A, B or C
    j = ord(arr[i][0])-65
    # Extend corresponding string list
    res[j].extend([arr[i]])

for i in range(len(res)):
    print(res[i])

But I get this result:

['A1', 'C3', 'B2', 'A2', 'C1', 'A3', 'B1', 'C2', 'A4']
['A1', 'C3', 'B2', 'A2', 'C1', 'A3', 'B1', 'C2', 'A4']
['A1', 'C3', 'B2', 'A2', 'C1', 'A3', 'B1', 'C2', 'A4']

Where am I wrong please? Thank you for your help!


Solution

  • The problem is due to the following: res = [[]] * 3 will create three lists, but all three are the same object. So whenever you append or extend one of them it will be added to "all" (they are all the same object after all).

    You can easily check this by replacing it with: res = [[],[],[]] which will then give you the expected answer.

    Consider these snippets:

    res = [[]]*2
    res[0].append(1)
    print(res)
    
    Out:
    [[1], [1]]
    

    While

    res = [[],[]]
    res[0].append(1)
    print(res)
    
    Out:
    [[1], []]
    

    Alternatively you can create the nested list like this: res = [[] for i in range(3)]