0

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!

2
  • Do you want to group elements based on their first character? Commented Mar 20, 2019 at 9:14
  • No. The criteria is different. In my real program, A1, B1 etc.. are file names. The trick must work whatever the strings. The answer is given by John Sloper in the comments ;-) [Edit: I have modified my initial code by adding brackets around arr[i] in extend function] Commented Mar 20, 2019 at 9:36

3 Answers 3

2

You can use itertools.groupby and group the elements in the list (having been sorted) according to the first element. You can use operator.itemgetter to efficiently fetch the first substring in each string:

from itertools import groupby
from operator import itemgetter

[list(v) for k,v in groupby(sorted(arr), key=itemgetter(0))]
# [['A1', 'A2', 'A3', 'A4'], ['B1', 'B2'], ['C1', 'C2', 'C3']]
Sign up to request clarification or add additional context in comments.

Comments

0

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)]

Comments

0

You can use list comprehension :

[[k for k in arr if k[0]==m] for m in sorted(set([i[0] for i in arr]))]

OUTPUT :

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.