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$

3 Answers 3

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$
4
  • $\begingroup$ I think it isn't grouping the lists if they aren't contiguous $\endgroup$ Commented Feb 18, 2013 at 4:34
  • 1
    $\begingroup$ Shouldn't that be GatherBy? $\endgroup$
    – Mr.Wizard
    Commented Feb 18, 2013 at 4:39
  • $\begingroup$ For some reason I interpreted the question as contiguous $\endgroup$
    – Rojo
    Commented Feb 18, 2013 at 4:46
  • $\begingroup$ Okay, fair enough. +1 $\endgroup$
    – Mr.Wizard
    Commented Feb 18, 2013 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
  • 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
    Commented Feb 18, 2013 at 15:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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