Objective-C NSString
에서 중복 값 ( ) 을 제거하는 가장 좋은 방법은 NSMutableArray
무엇입니까?
이것이 가장 쉽고 올바른 방법입니까?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
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];
[NSOrderedSet orderedSetWithArray:array];
그런 다음 처음부터 대신을 array = [orderedSet allObjects];
사용하거나 NSOrderedSet
s를 사용 하여 배열을 가져올 수 있습니다 NSArray
.
[orderedSet allObjects]
와 함께 [orderedSet array]
!
NSArray
temp를 가지고 있어야합니다 NSMutableArray
. 귀하의 예제에서는 반대의 반대를 작동
NSSet
) 또는 @Simon Whitaker 링크 가 효율적인 중복 값을 추가하기 전에 방지합니까?
나는 이것이 오래된 질문이라는 것을 알고 있지만 NSArray
주문에 신경 쓰지 않는다면 중복을 제거하는보다 우아한 방법이 있습니다.
Key Value Coding의 Object Operators를 사용 하면 다음과 같이 할 수 있습니다.
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
마찬가지로 AnthoPak이 또한 주목 그 속성에 기초하여 중복을 제거하는 것이 가능하다. 예를 들면 다음과 같습니다.@distinctUnionOfObjects.name
@distinctUnionOfObjects.property
사용자 정의 객체 배열의 속성으로 중복을 제거 하는 것과 같이 사용할 수도 있습니다 . 예를 들어@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 참조
주문이 필요하다
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]];
}
}
정렬 된 배열이있는 경우 배열의 다른 모든 항목을 확인하지 않아도 마지막 항목 만 확인할 수 있습니다. 모든 항목을 확인하는 것보다 훨씬 빠릅니다.
// sortedSourceArray is the source array, already sorted
NSMutableArray *newArray = [[NSMutableArray alloc] initWithObjects:[sortedSourceArray objectAtIndex:0]];
for (int i = 1; i < [sortedSourceArray count]; i++)
{
if (![[sortedSourceArray objectAtIndex:i] isEqualToString:[sortedSourceArray objectAtIndex:(i-1)]])
{
[newArray addObject:[tempArray objectAtIndex:i]];
}
}
등 같습니다 NSOrderedSet
또한 제안 답변이 훨씬 덜 코드가 필요하지만, 당신은을 사용할 수없는 경우 NSOrderedSet
어떤 이유로, 당신은 정렬 된 배열을 가지고, 내 솔루션은 빠른 것입니다 생각합니다. NSOrderedSet
솔루션 의 속도와 어떻게 비교되는지 잘 모르겠습니다 . 또한 내 코드가 확인 isEqualToString:
중이므로 동일한 일련의 문자가 두 번 이상 나타나지 않습니다 newArray
. NSOrderedSet
솔루션이 값이나 메모리 위치를 기반으로 중복을 제거 하는지 확실하지 않습니다 .
내 예는 s, just s 또는 둘의 혼합을 sortedSourceArray
포함 한다고 가정합니다 . 대신 s 또는 s 만 포함하는 경우 교체 할 수 있습니다.NSString
NSMutableString
sortedSourceArray
NSNumber
NSDate
if (![[sortedSourceArray objectAtIndex:i] isEqualToString:[sortedSourceArray objectAtIndex:(i-1)]])
와
if ([[sortedSourceArray objectAtIndex:i] compare:[sortedSourceArray objectAtIndex:(i-1)]] != NSOrderedSame)
완벽하게 작동합니다. s, s 및 / 또는 s sortedSourceArray
가 혼합되어 있으면 충돌이 발생했을 수 있습니다.NSString
NSNumber
NSDate
보다 세련된 솔루션을 제공하는 KVC 객체 연산자가 있습니다. NSArray 범주uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
는 다음과 같습니다 .
다음은 NSMutable Array에서 중복 값을 제거하는 코드입니다. 그것은 당신을 위해 일할 것입니다. myArray는 중복 값을 제거하려는 Mutable Array입니다.
for(int j = 0; j < [myMutableArray count]; j++){
for( k = j+1;k < [myMutableArray count];k++){
NSString *str1 = [myMutableArray objectAtIndex:j];
NSString *str2 = [myMutableArray objectAtIndex:k];
if([str1 isEqualToString:str2])
[myMutableArray removeObjectAtIndex:k];
}
} // Now print your array and will see there is no repeated value
이 간단한 코드를 사용하십시오.
NSArray *hasDuplicates = /* (...) */;
NSArray *noDuplicates = [[NSSet setWithArray: hasDuplicates] allObjects];
nsset은 중복 값을 허용하지 않으며 모든 객체가 배열을 반환하기 때문에
NSOrderedSet
insteed of을 사용 하십시오 NSSet
.