简体   繁体   中英

Python group by adjacent items in a list with same attributes

Please see the simplified example:

A=[(721,'a'),(765,'a'),(421,'a'),(422,'a'),(106,'b'),(784,'a'),(201,'a'),(206,'b'),(207,'b')]

I want group adjacent tuples with attribute 'a', every two pair wise and leave tuples with 'b' alone.

So the desired tuple would looks like:

 A=[[(721,'a'),(765,'a')],
    [(421,'a'),(422,'a')],
    [(106,'b')],
    [(784,'a'),(201,'a')],
    [(206,'b')],[(207,'b')]]

What I can do is to build two separated lists contains tuples with a and b .

Then pair tuples in a , and add back. But it seems not very efficient. Any faster and simple solutions?

You can use itertools.groupby :

import itertools
A=[(721,'a'),(765,'a'),(421,'a'),(422,'a'),(106,'b'),(784,'a'),(201,'a'),(206,'b'),(207,'b')]
def split(s):
  return [s[i:i+2] for i in range(0, len(s), 2)]

new_data = [i if isinstance(i, list) else [i] for i in list(itertools.chain(*[split(list(b)) if a == 'a' else list(b) for a, b in itertools.groupby(A, key=lambda x:x[-1])]))

Output:

[[(721, 'a'), (765, 'a')], [(421, 'a'), (422, 'a')], [(106, 'b')], [(784, 'a'), (201, 'a')], [(206, 'b')], [(207, 'b')]]

Assuming a items are always in pairs, a simple approach would be as follows.

Look at the first item - if it's an a , use it and the next item as a pair. Otherwise, just use the single item. Then 'jump' forward by 1 or 2, as appropriate:

A=[(721,'a'),(765,'a'),(421,'a'),(422,'a'),(106,'b'),(784,'a'),(201,'a'),(206,'b'),(207,'b')]

result = []
count = 0
while count <= len(A)-1:
    if A[count][1] == 'a':
        result.append([A[count], A[count+1]])
        count += 2
    else:
        result.append([A[count]])
        count += 1

print(result)

No need to use two lists. Edit: If the 'a' are not assumed to come always as pairs/adjacent

A = [(721,'a'),(765,'a'),(421,'a'),(422,'a'),(106,'b'),(784,'a'),(201,'a'),(206,'b'),(207,'b')]
new_list = []
i = 0
while i < len(A):
    if i == len(A)-1:
        new_list.append([A[i]])
        i+=1
    elif (A[i][1]==A[i+1][1]=='a') :
        new_list.append([A[i], A[i+1]])
        i += 2
    else:
        new_list.append([A[i]])
        i += 1
print(new_list)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM