wolfgang
wolfgang

Reputation: 7809

Further simplifying and shortening a simple grouping algorithm

This is the input list

input_list = ['string','string','1','string','2','string','string','3','string','5']

This is the output required

    [['string', 'string', '1'], ['string', '2'], ['string', 'string', '3'], 
     ['string', '5']]

Basically you're grouping the list data string and (numeric data) into a list of lists, each list containing the first numeric data and previous string data encountered

A simple algorithm which can accomplish this

output_list = []
inner_list = []
for data in input_list:
    inner_list.append(data)
    if data.isdigit():
        output_list.append(inner_list)
        inner_list = []

print output_list

I was wondering if this could be made even simpler (accomplished in lesser number of lines)?

Upvotes: 2

Views: 77

Answers (4)

mhawke
mhawke

Reputation: 87124

Even though this is a single line solution, it is not simpler, it's more complex:

input_list = ['string','string','1','string','2','string','string','3','string','5']
result = [s.split() for s in ' '.join([s+'\n' if s.isdigit() else s for s in input_list]).splitlines()]
print result

Output:

[['string', 'string', '1'], ['string', '2'], ['string', 'string', '3'], ['string', '5']]

Is this blob of complex code what you want?

(Note the bug: if one of the strings should already contain a \n. You could choose another character if you know for sure that it won't be in one of the strings).

Upvotes: 2

Kasravnd
Kasravnd

Reputation: 107347

You can first find the index of digit elements then use zip to create the desire slice indices and slice you list :

>>> ind=[0]+[i for i,j in enumerate(input_list,1) if j.isdigit()]
>>> [input_list[i:j] for i,j in zip(ind,ind[1:])]
[['string', 'string', '1'], ['string', '2'], ['string', 'string', '3'], ['string', '5']]

Upvotes: 3

Maltysen
Maltysen

Reputation: 1946

One liner with reduce. Do not use.

reduce(lambda n, e: n[:-1]+[n[-1]+[e]] + ([[]] if e.isdigit() else []), input_list, [[]])[:-1]

Upvotes: 3

dhke
dhke

Reputation: 15398

If you want a (slightly evil) reduce()-based version:

def reduce_string_prefix(cur, item):
    cur[-1].append(item)
    if item.isdigit():
        cur.append([])
    return cur

input_list = ['string', 'string', '1', 'string', '2', 'string', 'string', '3', 'string', '5']
output_list = reduce(reduce_string_prefix, input_list, [[]])[:-2]

I'm not so sure if this is actually easier to read, though ;-).

Upvotes: 1

Related Questions