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]]&;