This is just a slight correction (at least as I understood the problem) to the answer provided by the OP, @Anton. It is a very nice strategy, but it doesn't generalize and it doesn't reconstruct the connected components correctly according to the original list. For reference, here is @Anton's general strategy for a given list
of pairs:
ConnectedComponents@list /.
Join[
AssociationThread[list[[All, 1]] -> list],
AssociationThread[list[[All, 2]] -> list]]
Not generalizable
Let's say our list of pairs looks like this:
list = {{1, 2}, {1, 3}, {2, 3}, {10, 11}}
When we interpret this as edges of a graph, we will end up with vertices 4,5,6,7,8,9 just because of the default way WL builds graphs.
ConnectedComponents@list
(* {{1, 2, 3}, {10, 11}, {9}, {8}, {7}, {6}, {5}, {4}} *)
ConnectedComponents@list /. Join[AssociationThread[list[[All, 1]] -> list], AssociationThread[list[[All, 2]] -> list]]
(* {{{1, 3}, {1, 2}, {2, 3}}, {{10, 11}, {10, 11}}, {9}, {8}, {7}, {6}, {5}, {4}} *)
Creates duplicates
Given
list = {{1, 2}, {1, 3}, {2, 3}, {4, 5}, {5, 6}}
ConnectedComponents@list
(* {{4, 5, 6}, {1, 2, 3}} *)
ConnectedComponents@list /. Join[AssociationThread[list[[All, 1]] -> list], AssociationThread[list[[All, 2]] -> list]]
(* {{{4, 5}, {4, 5}, {5, 6}}, {{1, 3}, {1, 2}, {2, 3}}} *)
Notice that {4, 5}
is duplicated in the result. It might be that in the OP's data this case never occurs, but if so that wasn't made clear.
Doesn't recover all pairs
Consider this case:
list = {{1, 2}, {1, 3}, {1, 4}, {2, 3}, {3, 4}};
ConnectedComponents@list
(* {{1, 2, 3, 4}} *)
ConnectedComponents@list /. Join[AssociationThread[list[[All, 1]] -> list], AssociationThread[list[[All, 2]] -> list]]
(* {{{1, 4}, {1, 2}, {2, 3}, {3, 4}}} *)
Notice we've lost {1, 3}
. Since ReplaceAll
works on the list of connected vertices, anytime we have more edges than vertices, we'll lose edges.
Improved version
Let's keep the idea of using connected components, but since we're interpreting our original list of pairs as edges of a graph, it would be nice if we could use the built-in EdgeList
function for graphs to recover the edges in the connected components. We can do this if we could get the connected components as graphs themselves. Fortunately, that's what ConnectedGraphComponents
does.
list = {{1, 2}, {1, 3}, {2, 3}, {4, 5}, {5, 6}};
ConnectedGraphComponents@list
EdgeList /@ ConnectedGraphComponents@list
We can recover the pairs with
Apply[List, EdgeList /@ ConnectedGraphComponents@list, {2}]
(* {{{1, 2}, {1, 3}, {2, 3}, {1, 4}, {3, 4}}} *)
or alternatively with
EdgeList /@ ConnectedGraphComponents@list /. UndirectedEdge -> List
Let's apply this to our other test case:
list = {{1, 2}, {1, 3}, {2, 3}, {10, 11}};
EdgeList /@ ConnectedGraphComponents@list
Okay, we should eliminate the empty lists. I'll do it at the very end of the process:
DeleteCases[Apply[List, EdgeList /@ ConnectedGraphComponents@list, {2}], {}]
(* {{{1, 2}, {1, 3}, {2, 3}}, {{10, 11}}} *)
Applying this to the original list
:
list = {{1, 2}, {2, 3}, {4, 5}, {5, 6}, {7, 8}, {8, 9}, {9, 10},
{10, 11}, {11, 12}, {12, 13}, {13, 7}, {6, 14}, {14, 4},
{3, 15}, {15, 1}};
DeleteCases[Apply[List, EdgeList /@ ConnectedGraphComponents@list, {2}], {}]
(* {{{7, 8}, {13, 7}, {8, 9}, {12, 13}, {9, 10}, {10, 11}, {11, 12}},
{{4, 5}, {14, 4}, {5, 6}, {6, 14}},
{{1, 2}, {15, 1}, {2, 3}, {3, 15}}} *)
I kept the DeleteCases
for generality, it isn't strictly necessary in this case.
Gather
is that it expects some sort of equivalence relation, butIntersectingQ
isn't transitive. Something like that. It seems like whatGather
is doing is finding all the lists that are connected to{1,2}
, then removing these from the remaining list, then starting with the first one that doesn't connect, which is{4,5}
, and continuing that process. It's not iterative. $\endgroup$list = {{1, 2}, {2, 3}, {4, 5}, {5, 6}, {7, 8}, {8, 9}, {9, 10}, {10, 11}, {11, 12}, {12, 13}, {13, 7}, {6, 14}, {14, 4}, {3, 15}, {15, 1}, {1, 99}};
... $\endgroup$list = {{1, 2}, {1, 3}, {1, 4}, {2, 3}, {3, 4}}
. $\endgroup$