How to group items in list in python if the value change?

Question:

Suppose I have a list

msg_type =["sent-message", "received-message", "received-message", "sent-message", "received-message", "sent-message", "received-message", "received-message", "sent-message", "sent-message", "received-message", "sent-message", "sent-message", "received-message", "sent-message", "sent-message", "received-message", "sent-message", "received-message", "received-message", "sent-message", "sent-message", "received-message", "sent-message", "received-message", "sent-message", "received-message" ]

How would I be able to group this if there is change in next item

for ex: first set would be :
("sent-message", "received-message", "received-message")
second set would be:
("sent-message", "received-message")
and if sent-message repeats itself it should be in one group
"sent-message", "sent-message", "received-message"

I am able to achieve it for all other cases except the last one.
Basically I want to group them by single exchange

expected result:

conversations = [(0,2), (3,4),(5,7),(8,10), (11,13), (14,16),(17,19),(20,22),(23,24),(25,26)]
Asked By: Sanket Wagh

||

Answers:

Here’s a hacky solution. It returns the expected results, however I haven’t fully tested every use case. Hope this helps

def group_conversations(messages):
    conversations = []
    start = 0
    for k, v in enumerate(messages[1:]):
        if v == "sent-message":  # Switched
            if messages[k] == "sent-message":  # Sent 2 in a row, skip
                continue
            conversations += [[start, k]]
            start = k+1
    last_group = [[conversations[-1][1]+1, len(messages)-1]]  # Hack to grab the last conv which is excluded
    return conversations + last_group
Answered By: TheLazyScripter

You can try:

from itertools import groupby

out = []
for k, g in groupby(enumerate(msg_type), lambda k: k[1]):
    g = list(g)
    if k == "sent-message":
        out.append([g[0][0]])
    else:
        out[-1].append(g[-1][0])

print(out)

Prints:

[[0, 2], [3, 4], [5, 7], [8, 10], [11, 13], [14, 16], [17, 19], [20, 22], [23, 24], [25, 26]]
Answered By: Andrej Kesely