Mettre en évidence les éléments de la liste à l'aide de la correspondance de modèles

Nov 27 2020

À partir de ce qui suit list:

list = {{a, b, c}, {d, e, f}, {g, h, i}, {b, c, d}, {c, a, m}, {c, d, n}};

Je souhaite mettre en évidence les éléments listdont l'intersection est supérieure à 2.

Le code suivant ne peut pas obtenir le résultat souhaité:

list //. 
   {{a___, x:{_, _, _}, b___, y:{_, _, _}, c___} /; 
      Length@Intersection[x, y] >= 2 :> 
         {a, Style[x, Gray], b, Style[y, Gray], c}}

Le résultat souhaité est

J'ai également réfléchi Gather, mais cela changera l'ordre de la liste.

Mise à jour:
j'ai pensé à un moyen, pas élégant

list //. {a___,x:({_,_,_}|F[{_,_,_}]),b___,y:({_,_,_}),c___}/;
  Length[Intersection[x/.F->Identity,y]]>=2:>{a,F@x,b,F@y,c}
% /. F->Highlighted

Réponses

3 kglr Nov 27 2020 at 00:57
rg = RelationGraph[UnsameQ @ ## && Length@Intersection[##] >= 2 &, list]

hl = VertexList @ EdgeList @ rg
{{a, b, c}, {b, c, d}, {c, a, m}, {c, d, n}}
list /. x : Alternatives @@ hl :> Style[x, Gray] 

list /. x : Alternatives @@ hl :> Highlighted[x, BaseStyle -> Red]

HighlightGraph[rg, hl]

Vous pouvez également utiliser ConnectedComponentset sélectionner des composants avec plus d'un sommet:

ccs = Select[Length @ # >= 2 &] @ ConnectedComponents[rg]
 {{{a, b, c}, {b, c, d}, {c, a, m}, {c, d, n}}}
list /. x : Alternatives @@ # :> Highlighted[x, BaseStyle -> Red]& /@ ccs

2 MarcoB Nov 27 2020 at 00:44
ClearAll[formatList]
formatList[list_] := Module[{rules},
  rules =
    AssociationThread[
      list -> (If[Max[#] >= 2, Gray, Black] & /@ 
        Function[{element}, 
          Length@Intersection[element, #] & /@ 
           Complement[list, {element}]] /@ list)
    ];
  Style[#, rules[#]] & /@ list
]

formatList[list]

1 kglr Nov 27 2020 at 13:49

Une variante de la solution OP qui évite l'imbrication de Highlighted:

list //. {a___, x : ({_, _, _} | Highlighted[{_, _, _}, ___]), b___, 
    y : ({_, _, _}), c___} /; Length[Intersection[x /. Highlighted -> (# &), y]] >= 2 :> 
   {a, Highlighted[x /. Highlighted -> (# &)], b, Highlighted@y, c}

Même approche utilisant Style:

list //. {a___, x : ({_, _, _} | Style[{_, _, _}, ___]), b___, 
    y : ({_, _, _}), c___} /; Length[Intersection[x /. Style -> (# &), y]] >= 2 :> 
   {a, Style[x /. Style -> (# &), Gray], b, Style[y /. Style -> (# &), Gray], c}

1 cvgmt Nov 27 2020 at 16:02

Je pense que le moyen le plus simple est toujours d'utiliser Gatheret de réorganiser l'index. Ici, nous traitons la situation générale.

SeedRandom[400];
list = Table[RandomSample[Alphabet[], 3], 40];
newlist = Thread[Range[Length@list] -> list];
result = Gather[newlist, 
   Length[Intersection[Last@#1, Last@#2]] >= 2 &];
keys = Keys /@ result;
keyc = Thread[keys -> RandomColor[Length@keys]]
map[j_] := 
  MapAt[Style[#, Last@keyc[[j]], Bold] &, List /@ First@keyc[[j]]];
fig = Composition[Sequence @@ Table[map[j], {j, 1, Length@keyc}]]@
  list
Grid[Partition[fig, 8], Frame -> All]

1 kglr Nov 27 2020 at 17:52
list /. x : {__Symbol} /; 
  Max[Length[Intersection[x, #]] & /@ DeleteCases[list, x]] >= 2 :> 
    Style[x, Gray] 

Une méthode utilisant GatherBy:

gb = Join @@ Select[Length@# > 1 &]@
   GatherBy[list, Function[x, Max[Length[Intersection[x, #]] & /@ DeleteCases[x][list]]]]
 {{a, b, c}, {b, c, d}, {c, a, m}, {c, d, n}}
list /. x : Alternatives @@ gb :> Style[x, Gray]

Pourquoi Gatherne fonctionne pas:

Prenons un exemple plus simple:

list2 = Partition[Range@5, 3, 1];
GatherBy[list2, Function[x, Max[Length[Intersection[x, #]] & /@ 
  DeleteCases[x][list2]] >= 2]]
 {{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}}}
Gather[list2, Length[Intersection[##]] >= 2 &]
{{{1, 2, 3}, {2, 3, 4}},
 {{3, 4, 5}}}

Gathern'exécute pas la fonction de test sur toutes les paires de la liste d'entrée. Si la fonction de test évalue Truela paire {p1, p2}(de sorte que p1et p2soient regroupés), la paire {p1, p3}est testée mais {p2, p3}est ignorée comme on peut le voir dans la Tracesortie:

Trace[Gather[list2, Length[Intersection[##]] >= 2 &]] // Rest // Rest // Column

Notez que les triplets {2, 3, 4}et ne{3, 4, 5} sont pas comparés (car {2, 3, 4}est déjà rassemblé }.

kglr Nov 27 2020 at 20:51

Encore une autre approche consiste à prendre le Uniondes 2-sous-ensembles qui satisfont la condition:

highlighted = Union @@ Select[Length[Intersection @@ #] >= 2 &] @ Subsets[list, {2}]
{{a, b, c}, {b, c, d}, {c, a, m}, {c, d, n}}
list /. x : Alternatives @@ highlighted :> Style[x, Gray]