سؤال

في Mathematica لدي قائمة:

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

كيف سأقوم بعمل قائمة بالنسخ المكررة؟يحب:

{3,5}

لقد كنت أبحث في قوائم كمجموعات, ، إذا كان هناك شيء مثل باستثناء[] للقوائم، فيمكنني القيام بما يلي:

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

(بالطبع، إذا كانت x تحتوي على أكثر من نسختين - على سبيل المثال، {1،2,2,2,3,4,4}، سيكون الناتج {2,2,4}، لكن Union[] الإضافي سيحل هذه المشكلة.)

ولكن لم يكن هناك شيء من هذا القبيل (إذا كنت أفهم جميع الوظائف هناك جيدًا).

حتى كيف نفعل ذلك؟

هل كانت مفيدة؟

المحلول

هناك الكثير من الطرق للقيام باستخراج القائمة مثل هذه؛هذا هو أول ما يتبادر إلى ذهني:

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

أو بشكل أكثر قابلية للقراءة في القطع:

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

والذي يعطي، على التوالي،

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

ربما يمكنك التفكير في طريقة أكثر كفاءة (من حيث الوقت أو مساحة الكود). :)

بالمناسبة، إذا لم يتم فرز القائمة، فأنت بحاجة إلى التشغيل Sort عليه أولا قبل أن يعمل هذا.

نصائح أخرى

إليك طريقة للقيام بذلك في تمريرة واحدة عبر القائمة:

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]

من المحتمل أن يكون حل ويل روبرتسون أفضل لأنه أكثر وضوحًا، ولكن أعتقد أنه إذا كنت تريد الحصول على مزيد من السرعة، فيجب أن يفوز هذا الحل.لكن لو كنت مهتمًا بذلك، لما كنت تبرمج في Mathematica!:)

فيما يلي العديد من الاختلافات الأسرع في طريقة Tally.

f4 يستخدم "الحيل" التي قدمها كارل وول وأوليفر روبنكوينج على MathGroup.

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

إنه لأمر مدهش بالنسبة لي ذلك f4 ليس لديه أي نفقات عامة تقريبًا مقارنة بالنقية Tally!

يعد استخدام حل مثل dreeves، ولكن إرجاع مثيل واحد فقط لكل عنصر مكرر، أمرًا صعبًا بعض الشيء.إحدى طرق القيام بذلك هي كما يلي:

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 المتميز)، لأن العناصر ستظهر في القائمة التي تم إرجاعها بالترتيب الذي يمكن من خلاله تحديد أنها مكررة.لست متأكدًا مما إذا كان من الممكن فعل ذلك بتمريرة واحدة، فكل الطرق التي يمكنني التفكير فيها تتضمن، في الواقع، تمريرتين على الأقل، على الرغم من أن إحداهما قد تكون فقط فوق العناصر المكررة.

فيما يلي نسخة من إجابة روبرتسون التي تستخدم "تدوين postfix" بنسبة 100% لاستدعاءات الوظائف.

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

الرياضيات // يشبه النقطة لاستدعاءات الطريقة في اللغات الأخرى.على سبيل المثال، إذا تمت كتابة هذا بأسلوب C# / LINQ، فسيشبه ذلك

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

لاحظ أن لغة C# Where هو مثل الفنون القتالية المختلطة Select, و C # Select هو مثل الفنون القتالية المختلطة Map.

يحرر:تمت إضافة وسيطة وظيفة اختبار اختيارية، بشكل افتراضي SameQ.

يحرر:إليك إصدار يتناول تعليقي أدناه ويبلغ عن جميع المعادلات في مجموعة معينة مع وظيفة جهاز عرض تنتج قيمة بحيث تعتبر عناصر القائمة متكافئة إذا كانت القيمة متساوية.يؤدي هذا بشكل أساسي إلى العثور على فئات التكافؤ أطول من حجم معين:

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

فيما يلي عينة تتحقق من أزواج الأعداد الصحيحة في عناصرها الأولى، مع الأخذ في الاعتبار أن الزوجين متكافئين إذا كانت عناصرهما الأولى متساوية

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

يبدو هذا الموضوع قديمًا، لكن كان عليّ حله بنفسي.

هذا نوع من الخام، ولكن هل هذا يفعل ذلك؟

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

نظرا للقائمة أ،
احصل على القيم غير المكررة في B
ب = حذف التكرارات[A]
الحصول على القيم المكررة في C
ج = تكملة [أ، ب]
احصل على القيم غير المكررة من القائمة المكررة في D
D = حذف التكرارات[C]

لذلك على سبيل المثال الخاص بك:
أ = 1، 2، 2، 2، 3، 4، 4
ب = 1، 2، 3، 4
ج = 2، 2، 4
د = 2، 4

لذلك ستكون إجابتك حذف التكرارات[Complement[x,DeleteDuplicates[x]]] حيث x هي قائمتك.لا أعرف الرياضيات، لذا قد يكون بناء الجملة مثاليًا هنا وقد لا يكون كذلك.ما عليك سوى الاطلاع على المستندات الموجودة على الصفحة التي قمت بالارتباط بها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top