NSSet에서 객체 가져 오기


답변:


139

세트에 대한 몇 가지 사용 사례가 있습니다. 열거 (예 : enumerateObjectsUsingBlock또는 NSFastEnumeration), containsObject멤버십 테스트 호출 anyObject, 멤버 가져 오기 (무작위 아님) 또는 다음을 사용하여 배열로 변환 (특정 순서 없음) 할 수 있습니다.allObjects 있습니다.

세트는 중복을 원하지 않고 주문에 신경 쓰지 않고 빠른 멤버십 테스트를 원할 때 적합합니다.


7
세트 member:메시지를 보내 잠재적 중복으로 알려진 개체를 찾을 수도 있습니다 . 을 반환 nil하면 세트에는 전달한 것과 동일한 객체가 포함되지 않습니다. 객체 포인터를 반환하면 반환하는 포인터는 이미 세트에있는 객체에 대한 것입니다. 세트의 객체가 구현해야 hash하고 isEqual:이 유용 할 수 있습니다.
— Peter Hosey

@PeterHosey 구현할 hash 필요 가 없다고 생각 합니다 . 그렇게한다면 훨씬 더 빨라질 것입니다.
— fumoboy007

2
@ fumoboy007 : 세트에 저장하거나 사전의 키로 사용하려면 그렇습니다. hashNSObject 프로토콜 의 문서 에서 : "두 개체가 동일한 경우 ( isEqual:메서드에 의해 결정됨) 두 개체는 동일한 해시 값을 가져야합니다." 현재의 NSObject의의 구현 hash및 isEqual:개체의 ID (주소)를 사용합니다. 를 재정의 isEqual:하면 동일하지는 않지만 동일한 개체의 가능성을 설정하는 것입니다.이 개체도 재정의하지 않으면 hash다른 해시를 갖게됩니다. 이는 동일한 객체에 동일한 해시가 있어야한다는 요구 사항을 위반합니다.
— 피터 호시

1
@ fumoboy007 : 해시 테이블의 작동 방식 고려 : 컨테이너에는 몇 개의 버킷 배열이 있으며 각 수신 객체의 해시를 사용하여 객체가 있어야하는 버킷을 결정합니다.와 같은 조회의 member:경우 컨테이너는 해당 버킷 만 찾습니다. 버킷 (이것이 멤버십 테스트에서 집합이 배열보다 훨씬 빠르고 키-값 조회에서 사전이 병렬 배열보다 훨씬 빠른 이유입니다). 찾고있는 객체에 잘못된 해시가있는 경우 컨테이너는 잘못된 버킷을보고 일치 항목을 찾지 못합니다.
— Peter Hosey

@PeterHosey 죄송합니다…의 기본 구현 -[NSObject hash]이 0 이라고 잘못 생각했습니다 . 그게 많은 것을 설명합니다. = S
— fumoboy007

31

NSSet에는 objectAtIndex 메소드가 없습니다.

모든 객체의 NSArray를 반환하는 allObjects를 호출 해보십시오.


반환 된 배열이 주문되었는지 아십니까? 즉, "setByAddingObject"를 사용하여 집합에 개체를 추가하고 "allObjects"를 사용하면 무엇입니까? 객체를 추가 한 순서대로 정렬 된 배열의 요소?
— iosMentalist

단지 정렬을 초래하는 NSSortPredicate와 배열 당신은 괜찮을거야
— 제이슨

하나의 특정 개체에만 관심이있는 경우 filtersSetUsingPredicate 접근 방식을 사용하는 것이 좋습니다.
— akw

17

필요한 개체를 선택할 수있는 고유 식별자가있는 경우에는 filtersSetUsingPredicate를 사용할 수 있습니다.

먼저 술어를 작성하십시오 (객체의 고유 ID가 "식별자"이고 NSString이라고 가정).

NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];

그런 다음 조건자를 사용하여 개체를 선택합니다.

NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;

13

NSArray *myArray = [myNSSet allObjects];

MyObject *object = [myArray objectAtIndex:(NSUInteger *)]

NSUInteger를 원하는 개체의 인덱스로 바꿉니다.


1
이어야합니다 : MyObject * object = [myArray objectAtIndex : (NSUInteger *)]
— John D.

8

Swift3 및 iOS10의 경우 :

//your current set
let mySet : NSSet
//targetted index
let index : Int
//get object in set at index
let object = mySet.allObjects[index]

6

NSSet은 isEqual : 메소드를 사용합니다 (해시 메소드와 함께 해당 세트에 넣은 객체가 오버라이드해야 함). 객체가 그 안에 있는지 확인합니다.

예를 들어 ID 값으로 고유성을 정의하는 데이터 모델이있는 경우 (예 : 속성은 다음과 같습니다.

@property NSUInteger objectID;

그런 다음 isEqual : as

- (BOOL)isEqual:(id)object
{
  return (self.objectID == [object objectID]);
}

해시를 구현할 수 있습니다.

- (NSUInteger)hash
{
 return self.objectID;  // to be honest, I just do what Apple tells me to here
                       // because I've forgotten how Sets are implemented under the hood
}

그런 다음 다음을 사용하여 해당 ID를 가진 객체를 가져올 수 있습니다 (NSSet에 있는지 확인).

MyObject *testObject = [[MyObject alloc] init];
testObject.objectID = 5; // for example.  

// I presume your object has more properties which you don't need to set here 
// because it's objectID that defines uniqueness (see isEqual: above)

MyObject *existingObject = [mySet member: testObject];

// now you've either got it or existingObject is nil

그러나 네, NSSet에서 무언가를 얻는 유일한 방법은 처음에 그것의 고유성을 정의하는 것을 고려하는 것입니다.

더 빠른 것을 테스트하지는 않았지만, 열거 형은 선형적일 수 있지만 member : 메서드를 사용하는 것이 훨씬 빠르기 때문에 사용하지 않습니다. 이것이 NSArray 대신 NSSet 사용을 선호하는 이유 중 하나입니다.



0

대부분의 경우 세트에서 하나의 특정 개체를 가져 오는 데 관심이 없습니다. 세트에 객체가 포함되어 있는지 테스트하는 데 관심이 있습니다. 그것이 세트가 좋은 이유입니다. 객체가 컬렉션에 있는지 확인하려는 경우 집합이 배열보다 훨씬 빠릅니다.

어떤 물건을 얻을지 신경 쓰지 않는다면 -anyObject가방에 손을 넣고 무언가를 잡는 것과 같이 세트에서 하나의 물건 만주는 것을 사용하십시오.

Dog *aDog = [dogs anyObject]; // dogs is an NSSet of Dog objects

어떤 객체를 얻는 지 신경 -member쓰면 객체를 돌려주는 사용 을 사용 하거나 세트에 없으면 nil을 사용하십시오. 호출하기 전에 이미 개체가 있어야합니다.

Dog *spot = [Dog dogWithName:@"Spot"];
// ...
Dog *aDog = [dogs member:spot]; // Returns the same object as above

더 많은 것을 이해하기 위해 Xcode에서 실행할 수있는 코드는 다음과 같습니다.

NSString *one = @"One";
NSString *two = @"Two";
NSString *three = @"Three";

NSSet *set = [NSSet setWithObjects:one, two, three, nil];

// Can't use Objective-C literals to create a set.
// Incompatible pointer types initializing 'NSSet *' with an expression of type 'NSArray *'
//  NSSet *set = @[one, two, three];

NSLog(@"Set: %@", set);
// Prints looking just like an array but is actually not in any order
//Set: {(
//     One,
//     Two,
//     Three
//     )}

// Get a random object
NSString *random = [set anyObject];
NSLog(@"Random: %@", random); // Random: One

// Iterate through objects. Again, although it prints in order, the order is a lie
for (NSString *aString in set) {
    NSLog(@"A String: %@", aString);
}

// Get an array from the set
NSArray *array = [set allObjects];
NSLog(@"Array: %@", array);

// Check for an object
if ([set containsObject:two]) {
    NSLog(@"Set contains two");
}

// Check whether a set contains an object and return that object if it does (nil if not)
NSString *aTwo = [set member:two];
if (aTwo) {
    NSLog(@"Set contains: %@", aTwo);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.