7
$\begingroup$

I have a list of lists, and I'd like to build a new list, in which lists are in the same list if they have the same first and last element. Here's an example. Suppose I have

{{1, 2, 4}, {1, 3, 4}, {1, 2, 4, 5}, {1, 3, 4, 5}, {2, 4, 5}, {3, 4, 5}}

After some magic has happened, I would like to have

{ {{1, 2, 4}, {1, 3, 4}}, {{1, 2, 4, 5}, {1, 3, 4, 5}}, {{2, 4, 5}}, {{3, 4, 5}} }

I was looking at Select and the others, but I can only come with ugly explicit loops that achieve this. I'm sure there's a nicer way of doing this. What could that be?

$\endgroup$
7
$\begingroup$

The following shall group the lists notwithstanding their order:

list = {{1, 2, 4}, {1, 3, 4}, {1, 2, 4, 5}, {1, 3, 4, 4}, {2, 4, 5}, {3, 4, 5}};
GatherBy[list, {First@#, Last@#} &]

(*
{{{1, 2, 4}, {1, 3, 4}, {1, 3, 4, 4}}, {{1, 2, 4, 5}}, {{2, 4, 5}}, {{3, 4, 5}}}
*)
$\endgroup$
5
$\begingroup$
list={{1, 2, 4}, {1, 3, 4}, {1, 2, 4, 5}, {1, 3, 4, 5}, {2, 4, 5}, {3, 4, 5}};

SplitBy[list, #[[{1, -1}]] &]
(* {{{1, 2, 4}, {1, 3, 4}}, {{1, 2, 4, 5}, {1, 3, 4, 5}}, {{2, 4, 5}}, {{3, 4, 5}}} *)
$\endgroup$
  • $\begingroup$ I think it isn't grouping the lists if they aren't contiguous $\endgroup$ – Dr. belisarius Feb 18 '13 at 4:34
  • 1
    $\begingroup$ Shouldn't that be GatherBy? $\endgroup$ – Mr.Wizard Feb 18 '13 at 4:39
  • $\begingroup$ For some reason I interpreted the question as contiguous $\endgroup$ – Rojo Feb 18 '13 at 4:46
  • $\begingroup$ Okay, fair enough. +1 $\endgroup$ – Mr.Wizard Feb 18 '13 at 4:50
1
$\begingroup$
 list = {{1, 2, 4}, {1, 3, 4}, {1, 2, 4, 5}, {1, 3, 4, 4}, {2, 4, 5}, {3, 4, 5}};
 gthr[l_] :=  Cases[l, #] & /@ DeleteDuplicates[{#[[1]], ___, #[[-1]]} & /@ l] 
 gthr[list]
 (* { {{1,2,4},{1,3,4},{1,3,4,4}}, {{1,2,4,5}}, {{2,4,5}}, {{3,4,5}}} *)

Update: gthr decoded:

Form patterns from the first and last members of sublists in list:

 {#[[1]], ___, #[[-1]]}& /@ list   
 (* {{1, ___, 4}, {1, ___, 4}, {1, ___, 5}, {1, ___, 4}, {2, ___, 5}, {3, ___, 5}}*)

Remove duplicate elements from the list of patterns:

 DeleteDuplicates[%] 
 (* {{1, ___, 4}, {1, ___, 5}, {2, ___, 5}, {3, ___, 5}} *)

For each pattern get the elements in list matching that pattern:

 Cases[list,#]&/@%  
 (* { {{1,2,4},{1,3,4},{1,3,4,4}}, {{1,2,4,5}}, {{2,4,5}}, {{3,4,5}}} *)
$\endgroup$
  • 1
    $\begingroup$ This is cool, but could you add a little explanation of what your code does for the benefit of less experienced future visitors? $\endgroup$ – Verbeia Feb 18 '13 at 15:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.