13

Mathematica にはリストがあります:

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

重複したリストを作成するにはどうすればよいですか? お気に入り:

{3,5}

Lists as Setsを見てきましたが、リストに Except[] のようなものがある場合は、次のことができます。

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

(もちろん、x に 2 つ以上の重複がある場合、たとえば {1, 2,2,2 ,3,4,4} の場合、出力は {2,2,4} になりますが、追加の Union[]これで解決します。)

しかし、そのようなことはありませんでした(すべての機能をよく理解していれば)。

それで、それを行う方法は?

4

8 に答える 8

13

このようにリスト抽出を行う方法はたくさんあります。これが私の頭に浮かんだ最初のことです:

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

または、より読みやすいように、次のようにします。

タリー@x
Select[%, Part[#, 2] > 1 &]
一部[%, すべて, 1]

それぞれ、

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

おそらく、より効率的な(時間またはコード空間で)方法を考えることができます:)

ちなみに、リストがソートされていない場合、Sortこれが機能する前に最初に実行する必要があります。

于 2009-10-27T14:39:36.580 に答える
7

リストを1回通過する方法は次のとおりです。

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

例えば:

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

一意の重複のリストが必要な場合 -- {1, 4, 2}-- 次に、上記を でラップしますDeleteDuplicates。これは、リストを介した別の単一パスです (Union結果もソートするため、効率が低下します)。

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

Will Robertson のソリューションは、単純であるという理由だけでおそらく優れていますが、速度を上げたい場合は、これが勝つはずです。しかし、それを気にするなら、あなたは Mathematica でプログラミングしていないでしょう! :)

于 2009-10-27T17:17:26.853 に答える
7

Tally メソッドのより高速なバリエーションをいくつか示します。

f4MathGroup で Carl Woll と Oliver Ruebenkoenig によって提供された「トリック」を使用します。

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

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

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

速度比較(f1参考までに掲載)

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

純粋f4Tally!

于 2011-03-09T22:36:44.333 に答える
4

dreeves のようなソリューションを使用して、複製された各要素の 1 つのインスタンスのみを返すのは、少し注意が必要です。それを行う1つの方法は次のとおりです。

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

これは、Will Robertson (IMO 上位) のソリューションによって生成された出力と正確には一致しません。これは、要素が重複していると判断できる順序で返されるリストに表示されるためです。本当に 1 回のパスで実行できるかどうかはわかりません。考えられるすべての方法には、事実上、少なくとも 2 つのパスが含まれます。

于 2009-10-27T20:01:46.570 に答える
2

このスレッドは古いようですが、自分で解決する必要がありました。

これはちょっと大雑把ですが、これでうまくいきますか?

Union[Select[Table[If[tt[[n]] == tt[[n + 1]], tt[[n]], ""], {n, Length[tt] - 1}], IntegerQ]]
于 2012-07-30T16:53:23.840 に答える
2

これは、関数呼び出しに100%「後置表記」を使用するRobertsonの回答のバージョンです。

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

Mathematica の//ドットは、他の言語のメソッド呼び出しのドットに似ています。たとえば、これを C# / LINQ スタイルで記述すると、次のようになります。

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

C# は MMA に似ており、C# は MMA に似Whereていることに注意してください。SelectSelectMap

編集: オプションのテスト関数引数を追加しました。デフォルトはSameQです。

EDIT:これは、以下の私のコメントに対処し、値が等しい場合にリストの要素が同等と見なされるような値を生成するプロジェクター関数を指定して、グループ内のすべての同等物を報告するバージョンです。これは基本的に、指定されたサイズよりも長い等価クラスを見つけます。

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

最初の要素が等しい場合に 2 つのペアが等しいと見なして、最初の要素で整数のペアをチェックするサンプルを次に示します。

reportDuplicateClusters[RandomInteger[10, {10, 2}], #[[1]] &]
于 2011-12-29T18:04:25.767 に答える
1

リスト A を指定
して、B の重複しない値を取得します
B = DeleteDuplicates[A]
C の重複する値を取得します
C = Complement[A,B]
D の重複するリストから重複しない値を取得します
D = DeleteDuplicates[C ]

たとえば、
A = 1、2、2、2、3、4、4
B = 1、2、3、4
C = 2、2、4
D = 2、4

したがって、あなたの答えは DeleteDuplicates[Complement[x,DeleteDuplicates[x]]] で、x はあなたのリストです。私は mathematica を知らないので、ここでの構文は完璧かもしれませんし、そうでないかもしれません。リンク先のページのドキュメントを参照するだけです。

于 2009-10-27T14:39:54.020 に答える