Menghapus duplikat setelah kejadian n
Sebagai generalisasi DeleteDuplicates
, saya ingin menghapus duplikat dari daftar, tetapi hanya setelah n
jumlah duplikat.
Katakanlah, n = 3
berarti tiga duplikat diperbolehkan.
Saya membuat fungsi saya sendiri:
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}
Apakah ada metode yang lebih baik - lebih cepat atau lebih elegan?
Misalnya, hanya menggunakan DeleteDuplicates
atau DeleteDuplicatesBy
?
Jawaban
Saya pikir Anda akan menemukan ini lebih cepat:
dd[list_, n_] :=
Module[{pi = Flatten[Values[PositionIndex[list][[All, ;; UpTo@n]]]]},
list[[Sort@pi]]];
Menggunakan RandomInteger[20000, 20000]
sebagai daftar tes dan mengizinkan 3 duplikat, kode Anda membutuhkan ~ 37 detik, ini membutuhkan ~ 0,03 detik.
Sebanding dengan kecepatan, lebih sederhana:
dd2[list_, n_] :=
list[[Union @@
GatherBy[Range@Length@list, list[[#]] &][[All, ;; UpTo@n]]]];
Untuk daftar besar yang bukan merupakan elemen duplikat besar, ini menawarkan keunggulan kinerja (misalnya, dengan RandomInteger[10000000,20000000]
daftar pengujian, lebih dari 6X kecepatan metode di atas):
dd=Module[{o = Ordering@#},
o[[o]] = Join @@ Range[Tally[#[[o]]][[All, 2]]];
Pick[#, UnitStep[#2 - o], 1]]&;