NSSet에서 객체 가져 오기


답변:


139

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

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


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

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

2
@ fumoboy007 : 세트에 저장하거나 사전의 키로 사용하려면 그렇습니다. hashNSObject 프로토콜 의 문서 에서 : "두 개체가 동일한 경우 ( isEqual:메서드에 의해 결정됨) 두 개체는 동일한 해시 값을 가져야합니다." 현재의 NSObject의의 구현 hashisEqual:개체의 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.