Mathematica에서 복제를 표시합니다
-
06-07-2019 - |
문제
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}이지만 추가 연합 []는 이것을 해결할 것입니다.)
그러나 그런 것은 없었습니다 (내가 거기에 모든 기능을 잘 이해했다면).
그래서 어떻게해야합니까?
해결책
이와 같은 추출을 목록하는 많은 방법; 내 마음에 처음으로 온 것은 다음과 같습니다.
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]
Will Robertson의 솔루션은 아마도 더 간단하기 때문에 더 나을 것입니다. 그러나 더 빠른 속도를 높이고 싶다면 이것이 이길 것이라고 생각합니다. 그러나 당신이 그것에 관심이 있다면, 당신은 Mathematica에서 프로그래밍되지 않을 것입니다! :)
다음은 탈리 방법의 몇 가지 빠른 변형입니다.
f4
MathGroup에서 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
그것은 나에게 놀랍습니다 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 Superior) 솔루션이 생성 한 출력과 정확히 일치하지 않습니다. 요소는 복제 된 것으로 결정할 수있는 순서대로 요소가 반환 된 목록에 나타나기 때문입니다. 나는 그것이 단일 패스로 실제로 할 수 있는지 확실하지 않으며, 내가 생각할 수있는 모든 방법은 실제로 두 번의 패스를 포함하지만, 하나는 복제 된 요소를 넘어 설 수 있습니다.
다음은 함수 호출에 100% "PostFix 표기법"을 사용하는 Robertson의 답변 버전입니다.
identifyDuplicates[list_List, test_:SameQ] :=
list //
Tally[#, test] & //
Select[#, #[[2]] > 1 &] & //
Map[#[[1]] &, #] &
수학자 //
다른 언어로 된 메소드 호출의 DOT와 유사합니다. 예를 들어, 이것이 C# / LINQ 스타일로 작성된 경우 유사합니다.
list.Tally(test).Where(x => x[2] > 1).Select(x => x[1])
C#의 경우에 유의하십시오 Where
MMA와 같습니다 Select
, 및 C#의 Select
MMA와 같습니다 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]]
목록 A가 주어지면
b에서 비면성 값을 얻으십시오
b = deleteduplicates [a
c에서 중복 값을 가져옵니다
C = 보완 [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
따라서 귀하의 답변은 삭제 된 [x, deleteduplicates [x]]] 여기서 x가 목록입니다. 나는 Mathematica를 모르기 때문에 구문이 여기에서 완벽하거나 완벽하지 않을 수도 있습니다. 링크 한 페이지의 문서로 이동합니다.