Question

Dans Mathematica, j'ai une liste:

x = {1,2,3,3,4,5,5,6}

Comment vais-je faire une liste avec les doublons? J'aime:

{3,5}

J'ai consulté Listes en tant qu'ensembles , s'il y a quelque chose comme: Sauf que [] pour les listes, je pourrais donc faire:

unique = Union[x]
duplicates = MyExcept[x,unique]

(Bien sûr, si le x avait plus de deux doublons, par exemple, {1, 2,2,2 , 3,4,4}, le résultat serait {2, 2,4}, mais une Union supplémentaire [] résoudrait ce problème.)

Mais il n’y avait rien de tel (si j’avais bien compris toutes les fonctions).

Alors, comment faire ça?

Était-ce utile?

La solution

Beaucoup de façons de faire une extraction de liste comme celle-ci; voici la première chose qui m'est venue à l'esprit:

Part[Select[Tally@x, Part[#, 2] > 1 &], All, 1]

Ou, plus facilement, en morceaux:

Tally@x
Select[%, Part[#, 2] > 1 &]
Part[%, All, 1]

qui donne respectivement

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

Peut-être pourriez-vous penser à une manière plus efficace (en temps ou en espace de code) :)

En passant, si la liste n'est pas triée, vous devez d'abord exécuter Trier avant que cela fonctionne.

Autres conseils

Voici un moyen de le faire en un seul passage dans la liste:

collectDups[l_] := Block[{i}, i[n_]:= (i[n] = n; Unevaluated@Sequence[]); i /@ l]

Par exemple:

collectDups[{1, 1, 6, 1, 3, 4, 4, 5, 4, 4, 2, 2}] --> {1, 1, 4, 4, 4, 2}

Si vous voulez la liste des doublons uniques - {1, 4, 2} -, placez le texte ci-dessus dans DeleteDuplicates , qui est un autre passage unique à travers le La liste ( Union est moins efficace car elle trie également le résultat).

collectDups[l_] := 
  DeleteDuplicates@Block[{i}, i[n_]:= (i[n] = n; Unevaluated@Sequence[]); i /@ l]

La solution de Will Robertson est probablement meilleure simplement parce que c'est plus simple, mais je pense que si vous vouliez gagner plus de vitesse, cela devrait l'emporter. Mais si vous vous souciez de cela, vous ne feriez pas de programmation dans Mathematica! :)

Voici plusieurs variantes plus rapides de la méthode Tally.

f4 utilise des "astuces". donné par Carl Woll et Oliver Ruebenkoenig sur MathGroup.

f2 = Tally@# /. {{_, 1} :> Sequence[], {a_, _} :> a} &;

f3 = Pick[#, Unitize[#2 - 1], 1] & @@ Transpose@Tally@# &;

f4 = # ~Extract~ SparseArray[Unitize[#2 - 1]]["NonzeroPositions"] & @@ Transpose@Tally@# &;

Comparaison de la vitesse ( f1 inclus pour référence)

a = RandomInteger[100000, 25000];

f1 = Part[Select[Tally@#, Part[#, 2] > 1 &], All, 1] &;

First@Timing@Do[#@a, {50}] & /@ {f1, f2, f3, f4, Tally}

SameQ @@ (#@a &) /@ {f1, f2, f3, f4}

Out[]= {3.188, 1.296, 0.719, 0.375, 0.36}

Out[]= True

C’est étonnant pour moi que f4 n’ait pratiquement aucune surcharge par rapport à un pur compte !

Utiliser une solution telle que dreeves, mais ne renvoyer qu’une seule instance de chaque élément dupliqué est un peu compliqué. Une façon de le faire est la suivante:

collectDups1[l_] :=
  Module[{i, j},
    i[n_] := (i[n] := j[n]; Unevaluated@Sequence[]);
    j[n_] := (j[n] = Unevaluated@Sequence[]; n);
    i /@ l];

Cela ne correspond pas exactement au résultat produit par la solution de Will Robertson (OMI supérieure), car les éléments apparaîtront dans la liste renvoyée dans l'ordre dans lequel il sera déterminé qu'ils sont des doublons. Je ne sais pas si cela peut vraiment être fait en un seul passage. Toutes les façons dont je peux imaginer impliquent en fait au moins deux passages, bien que l'un puisse ne concerner que les éléments dupliqués.

Voici une version de la réponse de Robertson qui utilise 100% de " notation postfixée " pour les appels de fonction.

identifyDuplicates[list_List, test_:SameQ] :=
 list //
    Tally[#, test] & //
   Select[#, #[[2]] > 1 &] & //
  Map[#[[1]] &, #] &

Le // de Mathematica est similaire au point utilisé pour les appels de méthode dans d'autres langues. Par exemple, si cela était écrit en style C # / LINQ, cela ressemblerait à

list.Tally(test).Where(x => x[2] > 1).Select(x => x[1])

Notez que où C correspond à Select de MMA et que Select de C # est similaire à Map de MMA.

EDIT: ajout de l'argument facultatif de la fonction test, par défaut sur SameQ .

EDIT: voici une version qui répond à mon commentaire ci-dessous & amp; rapporte tous les équivalents d'un groupe étant donné une fonction de projecteur produisant une valeur telle que les éléments de la liste soient considérés comme équivalents si la valeur est égale. Cela permet essentiellement de trouver des classes d'équivalence plus longues qu'une taille donnée:

reportDuplicateClusters[list_List, projector_: (# &), 
  minimumClusterSize_: 2] :=
 GatherBy[list, projector] //
  Select[#, Length@# >= minimumClusterSize &] &

Voici un exemple qui vérifie des paires d'entiers sur leurs premiers éléments, en considérant deux paires équivalentes si leurs premiers éléments sont égaux

reportDuplicateClusters[RandomInteger[10, {10, 2}], #[[1]] &]

Ce fil semble vieux, mais je dois le résoudre moi-même.

C'est un peu grossier, mais est-ce que ça le fait?

Union[Select[Table[If[tt[[n]] == tt[[n + 1]], tt[[n]], ""], {n, Length[tt] - 1}], IntegerQ]]

Étant donné la liste A,
récupère les valeurs non dupliquées en B
B = DeleteDuplicates [A]
récupère les valeurs en double en C
C = complément [A, B]
obtenir les valeurs non dupliquées de la liste de doublons en D

D = DeleteDuplicates [C]

Donc, pour votre exemple:
A = 1, 2, 2, 2, 3, 4, 4
B = 1, 2, 3, 4
C = 2, 2, 4
D = 2, 4

donc votre réponse serait DeleteDuplicates [Complement [x, DeleteDuplicate [x]]] où x est votre liste. Je ne connais pas mathematica, la syntaxe peut donc ne pas être parfaite ici. Aller juste par la documentation sur la page à laquelle vous avez accédé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top