Learner
Learner

Reputation: 91

How to group or batch the list of elements based on indices sublist?

How to group or batch the list of elements based on indices sublist ? Below are the possible instances should be considered. Hope that helps better.

1st Instance : Length of elements == sum of all indices elements

indices = [1, 3, 5]
elements = ['A','B','C','D','E','F','G','H','I']

Output:
[['A'], ['B','C','D'],['E','F','G','H','I']]

2nd Instance : Length of elements > sum of all indices elements

Should consider max element of indices and then group accordingly elements list

indices = [1, 3, 5]
elements = ['A','B','C','D','E','F','G','H','I', 'J','K','L','M','N']

Output:
[['A'], ['B','C','D'],['E','F','G','H','I'],['J','K','L','M','N']]

3rd Instance : Length of elements > sum of all indices elements

Should consider max element of indices and then group accordingly elements list

indices = [1, 3, 5]
elements = ['A','B','C','D','E','F','G','H','I', 'J','K','L']

Output:
[['A'], ['B','C','D'],['E','F','G','H','I'],['J','K','L']]

4th Instance : Length of elements > sum of all indices elements

Should consider max element of indices and then group accordingly elements list

indices = [1, 3, 5]
elements = ['A','B','C','D','E','F','G','H','I', 'J','K','L','M','N','O','P','Q','R','S']

Output:
[['A'], ['B','C','D'],['E','F','G','H','I'],['J','K','L','M','N'], ['O','P','Q','R','S']]

5th Instance : Length of elements < sum of all indices elements

indices = [1, 3, 5]
elements = ['A','B','C']

Output:
[['A'], ['B','C']]

6th Instance : Length of elements < sum of all indices elements

indices = [1, 3, 5]
elements = ['A','B','C','D','E','F']

Output:
[['A'], ['B','C','D'],['E','F']]

How can I achieve this in Python ?

Upvotes: -1

Views: 34

Answers (2)

t9dupuy
t9dupuy

Reputation: 440

Without using itertools:

indices = [1, 3, 5]

def groupWith(elements, indices):
    if sum(indices)<len(elements):
        q, r = divmod(len(elements)-sum(indices), indices[-1])
        indices += [indices[-1]] * q + ([r] if r>0 else [])
    elif sum(indices)>len(elements):
        cumsum_indices = [sum(indices[:i+1]) for i in range(len(indices))]
        for j, e in enumerate(cumsum_indices):
            if e>len(elements):
                indices = indices[:j] + [len(elements)-sum(indices[:j])]
                break
    ret = []
    for idx, elem in enumerate(indices):
        start = int(idx>0) * sum(indices[:idx])
        ret += [elements[start:start+elem]]
    return ret
    
print(groupWith(['A','B','C','D','E','F','G','H','I'], indices))
print(groupWith(['A','B','C','D','E','F','G','H','I', 'J','K','L','M','N'], indices))
print(groupWith(['A','B','C','D','E','F','G','H','I', 'J','K','L'], indices))
print(groupWith(['A','B','C','D','E','F','G','H','I', 'J','K','L','M','N','O','P','Q','R','S'], indices))
print(groupWith(['A','B','C'], indices))
print(groupWith(['A','B','C','D','E','F'], indices))

Outputs:

[['A'], ['B', 'C', 'D'], ['E', 'F', 'G', 'H', 'I']]
[['A'], ['B', 'C', 'D'], ['E', 'F', 'G', 'H', 'I'], ['J', 'K', 'L', 'M', 'N']]
[['A'], ['B', 'C', 'D'], ['E', 'F', 'G', 'H', 'I'], ['J', 'K', 'L']]
[['A'], ['B', 'C', 'D'], ['E', 'F', 'G', 'H', 'I'], ['J', 'K', 'L', 'M', 'N'], ['O', 'P', 'Q', 'R', 'S']]
[['A'], ['B', 'C']]
[['A'], ['B', 'C', 'D'], ['E', 'F']]

Note: this is a bit crude and could very well be optimised.

Upvotes: 1

Andrej Kesely
Andrej Kesely

Reputation: 195543

You can use itertools.islice to slice the elements:

from itertools import islice

indices = [1, 3, 5]
elements = ['A','B','C','D','E','F','G','H','I', 'J','K','L','M','N','O','P','Q','R','S']

def get_cnt(indices):
    if len(indices) == 0:
        return
    yield from indices
    while True:
        yield indices[-1]

out, it, g = [], iter(elements), get_cnt(indices)
while slice_:=list(islice(it, next(g))):
    out.append(slice_)

print(out)

Prints:

[['A'], ['B', 'C', 'D'], ['E', 'F', 'G', 'H', 'I'], ['J', 'K', 'L', 'M', 'N'], ['O', 'P', 'Q', 'R', 'S']]

Upvotes: 1

Related Questions