문제

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를 모르기 때문에 구문이 여기에서 완벽하거나 완벽하지 않을 수도 있습니다. 링크 한 페이지의 문서로 이동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top