The second argument of group_lp serves as an accumulator to collect items with the same key. As long as the next item uses the same key, it is put into this accumulator (2nd clause). If the remaining list is empty (1st clause) or it starts with an element of a different key (3rd clause), the accumulated list is put into the output list.
:-mode group(+,-). group([],[]). group([H|T],K):- group_lp(T,[H],K). group_lp([],L,[L]). group_lp([H|T],[A|A1],K):- same_group(H,A), !, group_lp(T,[H,A|A1],K). group_lp([H|T],L,[L|K]):- group_lp(T,[H],K).
The order of the sub lists in the result is the same as the order of the keys in the original list.
If the initial list is not sorted by the same key that is used in same_group, then this program does not work at all.
:-mode group(+,+,-). group([],_,[]):- !. group(Terms,N,Grouped):- sort(N,=<,Terms,[H|T]), arg(N,H,Group), group1(T,Group,[H],N,Grouped). group1([],Group,L,_,[group(Group,L)]). group1([H|T],Group,L,N,Grouped):- arg(N,H,Group), !, group1(T,Group,[H|L],N,Grouped). group1([H|T],Old,L,N,[group(Old,L)|Grouped]):- arg(N,H,Group), group1(T,Group,[H],N,Grouped).