การลบรายการที่ซ้ำกันหลังจากที่เกิด n

Aug 19 2020

โดยทั่วไปDeleteDuplicatesแล้วฉันต้องการลบรายการที่ซ้ำกันออกจากรายการ แต่หลังจากnจำนวนรายการที่ซ้ำกันเท่านั้น

พูดn = 3หมายความว่าอนุญาตให้ทำซ้ำสามรายการ

ฉันทำหน้าที่ของตัวเอง:

DeleteDuplicatesN[x_, n_] := 
  x[[
    Sort[
      Flatten[#[[1 ;; Min[Length[#], n]]]& /@ 
       (Flatten[Position[x, #]]& /@ DeleteDuplicates[x])]]]]

DeleteDuplicatesN[{1, 2, 3, 2, 1, 1, 1, 2, 3, 5, 5, 5, 5, 1, 7, 4, 7, 1}, 3]
{1, 2, 3, 2, 1, 1, 2, 3, 5, 5, 5, 7, 4, 7}

มีวิธีการที่ดีกว่า - เร็วกว่าหรือสวยกว่า?

ตัวอย่างเช่นใช้เฉพาะDeleteDuplicatesหรือDeleteDuplicatesBy?

คำตอบ

21 ciao Aug 19 2020 at 22:41

ฉันคิดว่าคุณจะพบสิ่งนี้ได้เร็วขึ้น:

dd[list_, n_] := 
  Module[{pi = Flatten[Values[PositionIndex[list][[All, ;; UpTo@n]]]]},
   list[[Sort@pi]]];

ใช้RandomInteger[20000, 20000]เป็นรายการทดสอบและอนุญาตให้ทำซ้ำ 3 ครั้งรหัสของคุณใช้เวลา ~ 37 วินาทีซึ่งจำเป็น ~ 0.03 วินาที

เทียบเคียงความเร็วง่ายกว่า:

dd2[list_, n_] := 
  list[[Union @@ 
     GatherBy[Range@Length@list, list[[#]] &][[All, ;; UpTo@n]]]];

สำหรับรายการขนาดใหญ่ที่ไม่ได้ทำซ้ำองค์ประกอบอย่างสิ้นเชิงสิ่งนี้จะมอบความได้เปรียบด้านประสิทธิภาพ (เช่นด้วยRandomInteger[10000000,20000000]รายการทดสอบความเร็วมากกว่า 6 เท่าของวิธีการข้างต้น):

dd=Module[{o = Ordering@#},
 o[[o]] = Join @@ Range[Tally[#[[o]]][[All, 2]]];
 Pick[#, UnitStep[#2 - o], 1]]&;