Objective-C NSString
에서 중복 값 ( ) 을 제거하는 가장 좋은 방법은 NSMutableArray
무엇입니까?
이것이 가장 쉽고 올바른 방법입니까?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
답변
당신 NSSet
이 다시 객체의 순서에 대한 걱정,하지만하지 않는 경우 당신은 순서에 대해 걱정하지 않는 경우 접근 방법은 왜 당신은에 저장되지 않고, 최고 NSSet
와 함께 시작?
2009 년에 아래 답변을 썼습니다. 2011 년에 Apple NSOrderedSet
은 iOS 5 및 Mac OS X 10.7에 추가되었습니다 . 알고리즘은 이제 두 줄의 코드입니다.
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray];
NSArray *arrayWithoutDuplicates = [orderedSet array];
주문이 걱정되고 iOS 4 또는 이전 버전에서 실행중인 경우 배열 사본을 반복하십시오.
NSArray *copy = [mutableArray copy];
NSInteger index = [copy count] - 1;
for (id object in [copy reverseObjectEnumerator]) {
if ([mutableArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound) {
[mutableArray removeObjectAtIndex:index];
}
index--;
}
[copy release];
답변
나는 이것이 오래된 질문이라는 것을 알고 있지만 NSArray
주문에 신경 쓰지 않는다면 중복을 제거하는보다 우아한 방법이 있습니다.
Key Value Coding의 Object Operators를 사용 하면 다음과 같이 할 수 있습니다.
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
마찬가지로 AnthoPak이 또한 주목 그 속성에 기초하여 중복을 제거하는 것이 가능하다. 예를 들면 다음과 같습니다.@distinctUnionOfObjects.name
답변
예, NSSet을 사용하는 것이 현명한 방법입니다.
Jim Puls의 답변에 추가하려면 순서를 유지하면서 중복을 제거하는 다른 방법이 있습니다.
// Initialise a new, empty mutable array
NSMutableArray *unique = [NSMutableArray array];
for (id obj in originalArray) {
if (![unique containsObject:obj]) {
[unique addObject:obj];
}
}
본질적으로 Jim과 동일한 접근 방법이지만 원본에서 복제본을 삭제하는 대신 고유 한 항목을 새로운 가변 배열에 복사합니다. 이것은 많은 중복을 가진 큰 배열 (전체 배열의 사본을 만들 필요가 없음)의 경우 약간 더 메모리 효율적이며, 제 생각에는 좀 더 읽기 쉽습니다.
두 경우 모두 대상 배열에 항목이 이미 포함되어 있는지 ( containsObject:
내 예제 또는 indexOfObject:inRange:
Jim의 경우에) 확인하면 큰 배열에는 잘 맞지 않습니다. 이러한 검사는 O (N) 시간에 실행됩니다. 즉, 원래 배열의 크기를 두 배로 늘리면 각 검사 를 실행하는 데 두 배의 시간이 걸립니다. 배열의 각 객체에 대해 검사를 수행하므로 더 비싼 검사를 더 많이 실행하게됩니다. 전체 알고리즘 (광산과 Jim 모두)은 O (N 2 ) 시간에 실행되며 원래 배열이 커짐에 따라 빠르게 비싸집니다.
NSMutableSet
NSSet 조회가 O (N)가 아닌 O (1)이기 때문에 이를 O (N) 시간으로 낮추려면 a 를 사용하여 이미 새 배열에 추가 된 항목의 레코드를 저장할 수 있습니다 . 즉, 요소가 NSSet의 멤버인지 여부를 확인하면 세트에있는 요소 수에 관계없이 동일한 시간이 걸립니다.
이 접근법을 사용하는 코드는 다음과 같습니다.
NSMutableArray *unique = [NSMutableArray array];
NSMutableSet *seen = [NSMutableSet set];
for (id obj in originalArray) {
if (![seen containsObject:obj]) {
[unique addObject:obj];
[seen addObject:obj];
}
}
그래도 여전히 조금 낭비적인 것 같습니다. 우리는 원래 배열이 변경 가능하다는 질문이 명백해지면 여전히 새로운 배열을 생성하고 있으므로 중복 제거하고 메모리를 절약 할 수 있어야합니다. 이 같은:
NSMutableSet *seen = [NSMutableSet set];
NSUInteger i = 0;
while (i < [originalArray count]) {
id obj = [originalArray objectAtIndex:i];
if ([seen containsObject:obj]) {
[originalArray removeObjectAtIndex:i];
// NB: we *don't* increment i here; since
// we've removed the object previously at
// index i, [originalArray objectAtIndex:i]
// now points to the next object in the array.
} else {
[seen addObject:obj];
i++;
}
}
업데이트 : 유리 니야 조프 (Yuri Niyazov) 는 아마도 O (N) 시간에 실행 되기 때문에 마지막 대답은 실제로 O (N 2 ) 에서 실행된다고 지적했습니다removeObjectAtIndex:
.
(우리는 그것이 어떻게 구현되는지 알지 못하기 때문에 “아마도”라고 말하지만 가능한 한 구현은 인덱스 X에서 객체를 삭제 한 후 메소드가 인덱스 X + 1에서 배열의 마지막 객체까지 모든 요소를 반복한다는 것입니다 , 이전 인덱스로 이동합니다.이 경우 실제로 O (N) 성능입니다.)
그래서 뭘 할건데? 상황에 따라 다릅니다. 대규모 배열이 있고 적은 수의 복제본 만 기대하는 경우 전체 중복 제거 기능이 제대로 작동하여 중복 배열을 구축하지 않아도됩니다. 중복이 많이 예상되는 어레이가있는 경우 별도의 중복 제거 된 어레이를 구축하는 것이 가장 좋은 방법 일 것입니다. 여기서의 탈취는 big-O 표기법은 알고리즘의 특성만을 설명하며 주어진 상황에 가장 적합한 것을 명확하게 알려주지는 않습니다.
답변
iOS 5 이상 (전체 iOS 환경을 대상으로하는)을 대상으로하는 경우 가장 좋습니다 NSOrderedSet
. 중복을 제거하고의 순서를 유지합니다 NSArray
.
그냥 해
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray];
이제 고유 한 NSArray로 다시 변환 할 수 있습니다
NSArray *uniqueArray = orderedSet.array;
이 같은있는 NSArray 같은 동일한 방법을 가지고 있기 때문에 또는 단지 orderedSet를 사용 objectAtIndex:
, firstObject
등등합니다.
회원 가입 확인 contains
은 회원 가입 보다 더 빠릅니다 NSOrderedSet
.NSArray
자세한 체크 아웃을 위해 NSOrderedSet 참조
답변
OS X v10.7 이상에서 사용 가능합니다.
주문이 걱정되는 경우 올바른 방법
NSArray *no = [[NSOrderedSet orderedSetWithArray:originalArray]allObjects];
다음은 NSArray에서 중복 값을 순서대로 제거하는 코드입니다.
답변
주문이 필요하다
NSArray *yourarray = @[@"a",@"b",@"c"];
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourarray];
NSArray *arrayWithoutDuplicates = [orderedSet array];
NSLog(@"%@",arrayWithoutDuplicates);
또는 주문이 필요하지 않습니다
NSSet *set = [NSSet setWithArray:yourarray];
NSArray *arrayWithoutOrder = [set allObjects];
NSLog(@"%@",arrayWithoutOrder);
답변
여기에서 mainArray에서 중복 이름 값을 제거하고 결과를 NSMutableArray (listOfUsers)에 저장합니다.
for (int i=0; i<mainArray.count; i++) {
if (listOfUsers.count==0) {
[listOfUsers addObject:[mainArray objectAtIndex:i]];
}
else if ([[listOfUsers valueForKey:@"name" ] containsObject:[[mainArray objectAtIndex:i] valueForKey:@"name"]])
{
NSLog(@"Same object");
}
else
{
[listOfUsers addObject:[mainArray objectAtIndex:i]];
}
}