Frage

In Mathematica Ich habe eine Liste:

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

Wie werde ich eine Liste mit den Duplikaten machen? Wie:

{3,5}

Ich habe mich unter Listen als Sets , wenn es etwas gibt, wie außer [] für Listen, so konnte ich tun:

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

(Natürlich, wenn die x habe mehr als zwei Duplikate - sagen, {1, 2,2,2 , 3,4,4}, da der Ausgang wäre {2, 2,4}, aber zusätzliche Union [] würde dieses Problem lösen.)

Aber es wie das nichts war (wenn ich es gut, alle Funktionen tat verstehen).

So, wie das zu tun?

War es hilfreich?

Lösung

Viele Wege Liste Extraktion wie dies zu tun; hier ist das erste, was mir in den Sinn kam:

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

Oder mehr leserlich in Stücken:

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

das gibt jeweils

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

Vielleicht können Sie denken an eine effizientere (in Zeit oder Coderaum) Art und Weise :)

Durch die Art und Weise, wenn die Liste unsortiert ist, dann müssen Sie Sort darauf laufen, bevor dies funktionieren wird.

Andere Tipps

Hier ist ein Weg, um es in einem einzigen Durchlauf durch die Liste zu tun:

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

Zum Beispiel:

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

Wenn Sie die Liste der einzigartigen Duplikate - {1, 4, 2} - dann wickeln die oben in DeleteDuplicates, was ein weiterer Arbeitsgang durch die Liste ist (Union ist weniger effizient als es sortiert auch das Ergebnis)

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

Will Robertson-Lösung ist wahrscheinlich besser, nur weil es einfacher ist, aber ich denke, wenn man mehr Geschwindigkeit eek, will sollte diese gewinnen. Aber wenn man darüber gepflegt, würden Sie nicht in Mathematica Programmierung sein! :)

Hier sind einige schnelleren Varianten der Tally-Methode.

f4 verwendet "Trick" gegeben von Carl Woll und Oliver Ruebenkoenig auf MathGroup.

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

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

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

Geschwindigkeitsvergleich (f1 als Referenz enthalten)

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

Es ist erstaunlich für mich, dass f4 hat fast kein Overhead in Bezug auf eine reine Tally!

eine Lösung wie dreeves verwenden, aber nur eine einzige Instanz jedes duplizierte Element zurückkehrt, ist ein bisschen auf der kniffligen Seite. Eine Möglichkeit, es zu tun, ist wie folgt:

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

Dies ist gerade nicht die Ausgabe von Will Robertson (IMO superior) Lösung hergestellt übereinstimmen, da Elemente in der zurückgegebenen Liste in der Reihenfolge angezeigt werden, dass bestimmt werden kann, dass sie Duplikate sind. Ich bin mir nicht sicher, ob es wirklich in einem einzigen Durchgang durchgeführt werden, alle Möglichkeiten, wie ich denken kann, beinhalten in der Tat zumindest zwei Durchgänge, obwohl man nur über die doppelten Elemente sein könnten.

Hier ist eine Version von Robertson Antwort, die 100% „Postfixnotation“ für Funktionsaufrufe verwendet.

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

Mathematicas // ähnelt dem Punkt für Methodenaufrufe in anderen Sprachen. Zum Beispiel, wenn dies in C # / LINQ Stil geschrieben wurde, wäre es ähnlich

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

Beachten Sie, dass C # 's Where wie MMA Select ist, und C #' s Select ist wie MMA Map.

EDIT:. Optionales Testfunktionsargument hinzugefügt, um SameQ säumige

EDIT: Hier ist eine Version, die meinen Kommentar unten Adressen & Berichte alle Äquivalente in einer Gruppe eine Projektorfunktion gegeben, die einen Wert, so dass Elemente der Liste erzeugt gleichwertig angesehen werden, wenn der Wert gleich ist. Dies findet im Wesentlichen Äquivalenzklassen länger als eine gegebene Größe:

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

Hier ist ein Beispiel, die Paare von ganzen Zahlen auf ihren ersten Elementen überprüft, wenn man bedenkt zwei Paare gleichwertig, wenn ihre ersten Elemente gleich sind

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

Dieser Thread scheint alt, aber ich habe das selbst zu lösen.

Dies ist eine Art von rohen, aber das tut es?

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

eine Liste A gegeben,
erhalten die Nicht-doppelte Werte in B
B = deleteduplicates [A]
erhalten Sie die doppelten Werte in C
C = Complement [A, B]
erhalten die Nicht-doppelte Werte aus der Duplikatliste in D
D = deleteduplicates [C]

So für Ihr Beispiel:
A = 1, 2, 2, 2, 3, 4, 4
B = 1, 2, 3, 4
C = 2, 2, 4
D = 2, 4

so Ihre Antwort würde deleteduplicates sein [Complement [x, deleteduplicates [x]]], wobei x die Liste. Ich weiß nicht, Mathematica, so dass die Syntax kann hier perfekt oder nicht. Gehen Sie einfach durch die docs auf der Seite, die Sie verknüpft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top