정렬 된 키가있는 NSDictionary
기본적으로 연관 배열 (키와 값으로 문자열)로 사용중인 NSDictionary (plist에 저장 됨)가 있습니다. 응용 프로그램의 일부로 키 배열을 사용하고 싶지만 특정 순서 (정렬 알고리즘을 작성할 수있는 순서가 아님)로 지정하고 싶습니다. 나는 항상 별도의 키 배열을 저장할 수 있지만, 항상 사전의 키와 배열의 값을 업데이트하고 항상 일치하는지 확인해야했기 때문에 다소 까다로워 보입니다. 현재는 [myDictionary allKeys] 만 사용하고 있지만 분명히 임의의 비 보장 순서로 반환합니다. Objective-C에 누락 된 데이터 구조가 있습니까? 누구든지 이것을 더 우아하게 수행하는 방법에 대한 제안이 있습니까?
연관된 NSMutableArray 키를 갖는 솔루션은 그렇게 나쁘지 않습니다. NSDictionary의 서브 클래 싱을 피하고 접근 자 작성에주의를 기울이면 동기화를 유지하는 것이 너무 어렵지 않아야합니다.
실제 답변으로 게임에 늦었지만 CHOrderedDictionary 조사에 관심이있을 수 있습니다 . 키 순서를 유지하기위한 또 다른 구조를 캡슐화하는 NSMutableDictionary의 하위 클래스입니다. ( CHDataStructures.framework 의 일부입니다 .) 딕셔너리와 배열을 별도로 관리하는 것보다 더 편리하다고 생각합니다.
공개 : 이것은 내가 작성한 오픈 소스 코드입니다. 이 문제에 직면 한 다른 사람들에게 유용 할 수 있기를 바랍니다.
이것을 얻을 수있는 내장 된 방법은 없습니다. 그러나 간단한 논리가 작동합니다. 사전을 준비하는 동안 각 키 앞에 숫자 텍스트를 몇 개만 추가하면됩니다. 처럼
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:
@"01.Created",@"cre",
@"02.Being Assigned",@"bea",
@"03.Rejected",@"rej",
@"04.Assigned",@"ass",
@"05.Scheduled",@"sch",
@"06.En Route",@"inr",
@"07.On Job Site",@"ojs",
@"08.In Progress",@"inp",
@"09.On Hold",@"onh",
@"10.Completed",@"com",
@"11.Closed",@"clo",
@"12.Cancelled", @"can",
nil];
이제 모든 키를 배치 한 순서대로 가져 오는 동안 sortingArrayUsingSelector를 사용할 수 있다면.
NSArray *arr = [[dict allKeys] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
UIView에서 키를 표시하려는 위치에서 앞의 3 개 문자를 잘라냅니다.
NSDictionary를 하위 클래스로 만들려면 최소한 다음 메서드를 구현해야합니다.
- NSDictionary
-count
-objectForKey:
-keyEnumerator
- NSMutableDictionary
-removeObjectForKey:
-setObject:forKey:
- NSCopying / NSMutableCopying
-copyWithZone:
-mutableCopyWithZone:
- NSCoding
-encodeWithCoder:
-initWithCoder:
- NSFastEnumeration (Leopard 용)
-countByEnumeratingWithState:objects:count:
원하는 작업을 수행하는 가장 쉬운 방법은 조작하는 자체 NSMutableDictionary와 정렬 된 키 세트를 저장하는 NSMutableArray를 포함하는 NSMutableDictionary의 하위 클래스를 만드는 것입니다.
당신이 당신의 객체를 인코딩하기 위해가는 일은 없습니다 경우 구현 건너 생각할 수 -encodeWithCoder:
및-initWithCoder:
위의 10 개 메서드의 모든 메서드 구현은 호스팅 된 사전 또는 순서가 지정된 키 배열을 통해 직접 이동합니다.
내 작은 추가 사항 : 숫자 키로 정렬 (작은 코드에 대한 속기 표기 사용)
// the resorted result array
NSMutableArray *result = [NSMutableArray new];
// the source dictionary - keys may be Ux timestamps (as integer, wrapped in NSNumber)
NSDictionary *dict =
@{
@0: @"a",
@3: @"d",
@1: @"b",
@2: @"c"
};
{// do the sorting to result
NSArray *arr = [[dict allKeys] sortedArrayUsingSelector:@selector(compare:)];
for (NSNumber *n in arr)
[result addObject:dict[n]];
}
빠르고 더러운 :
사전 (이하 "myDict"라고 함)을 주문해야하는 경우 다음과 같이하십시오.
NSArray *ordering = [NSArray arrayWithObjects: @"Thing",@"OtherThing",@"Last Thing",nil];
그런 다음 사전을 주문해야 할 때 색인을 만듭니다.
NSEnumerator *sectEnum = [ordering objectEnumerator];
NSMutableArray *index = [[NSMutableArray alloc] init];
id sKey;
while((sKey = [sectEnum nextObject])) {
if ([myDict objectForKey:sKey] != nil ) {
[index addObject:sKey];
}
}
이제 * index 객체는 올바른 순서로 적절한 키를 포함합니다. 이 솔루션은 모든 키가 반드시 존재해야하는 것은 아니며, 우리가 다루는 일반적인 상황입니다.
For, Swift 3 . 다음 접근 방식을 시도하십시오
//Sample Dictionary
let dict: [String: String] = ["01.One": "One",
"02.Two": "Two",
"03.Three": "Three",
"04.Four": "Four",
"05.Five": "Five",
"06.Six": "Six",
"07.Seven": "Seven",
"08.Eight": "Eight",
"09.Nine": "Nine",
"10.Ten": "Ten"
]
//Print the all keys of dictionary
print(dict.keys)
//Sort the dictionary keys array in ascending order
let sortedKeys = dict.keys.sorted { $0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedAscending }
//Print the ordered dictionary keys
print(sortedKeys)
//Get the first ordered key
var firstSortedKeyOfDictionary = sortedKeys[0]
// Get range of all characters past the first 3.
let c = firstSortedKeyOfDictionary.characters
let range = c.index(c.startIndex, offsetBy: 3)..<c.endIndex
// Get the dictionary key by removing first 3 chars
let firstKey = firstSortedKeyOfDictionary[range]
//Print the first key
print(firstKey)
NSDictionary의 정렬 된 하위 클래스의 최소 구현 ( https://github.com/nicklockwood/OrderedDictionary 기반 ). 필요에 따라 자유롭게 확장하십시오.
Swift 3 및 4
class MutableOrderedDictionary: NSDictionary {
let _values: NSMutableArray = []
let _keys: NSMutableOrderedSet = []
override var count: Int {
return _keys.count
}
override func keyEnumerator() -> NSEnumerator {
return _keys.objectEnumerator()
}
override func object(forKey aKey: Any) -> Any? {
let index = _keys.index(of: aKey)
if index != NSNotFound {
return _values[index]
}
return nil
}
func setObject(_ anObject: Any, forKey aKey: String) {
let index = _keys.index(of: aKey)
if index != NSNotFound {
_values[index] = anObject
} else {
_keys.add(aKey)
_values.add(anObject)
}
}
}
용법
let normalDic = ["hello": "world", "foo": "bar"]
// initializing empty ordered dictionary
let orderedDic = MutableOrderedDictionary()
// copying normalDic in orderedDic after a sort
normalDic.sorted { $0.0.compare($1.0) == .orderedAscending }
.forEach { orderedDic.setObject($0.value, forKey: $0.key) }
// from now, looping on orderedDic will be done in the alphabetical order of the keys
orderedDic.forEach { print($0) }
목표 -C
@interface MutableOrderedDictionary<__covariant KeyType, __covariant ObjectType> : NSDictionary<KeyType, ObjectType>
@end
@implementation MutableOrderedDictionary
{
@protected
NSMutableArray *_values;
NSMutableOrderedSet *_keys;
}
- (instancetype)init
{
if ((self = [super init]))
{
_values = NSMutableArray.new;
_keys = NSMutableOrderedSet.new;
}
return self;
}
- (NSUInteger)count
{
return _keys.count;
}
- (NSEnumerator *)keyEnumerator
{
return _keys.objectEnumerator;
}
- (id)objectForKey:(id)key
{
NSUInteger index = [_keys indexOfObject:key];
if (index != NSNotFound)
{
return _values[index];
}
return nil;
}
- (void)setObject:(id)object forKey:(id)key
{
NSUInteger index = [_keys indexOfObject:key];
if (index != NSNotFound)
{
_values[index] = object;
}
else
{
[_keys addObject:key];
[_values addObject:object];
}
}
@end
용법
NSDictionary *normalDic = @{@"hello": @"world", @"foo": @"bar"};
// initializing empty ordered dictionary
MutableOrderedDictionary *orderedDic = MutableOrderedDictionary.new;
// copying normalDic in orderedDic after a sort
for (id key in [normalDic.allKeys sortedArrayUsingSelector:@selector(compare:)]) {
[orderedDic setObject:normalDic[key] forKey:key];
}
// from now, looping on orderedDic will be done in the alphabetical order of the keys
for (id key in orderedDic) {
NSLog(@"%@:%@", key, orderedDic[key]);
}
저는 C ++를별로 좋아하지 않지만 제가 점점 더 많이 사용하고있는 한 가지 해결책은 Objective-C ++와 std::map
표준 템플릿 라이브러리를 사용하는 것입니다. 삽입시 키가 자동으로 정렬되는 사전입니다. 스칼라 유형이나 Objective-C 객체 모두 키와 값으로 놀랍도록 잘 작동합니다.
배열을 값으로 포함해야하는 경우 std::vector
대신을 사용하십시오 NSArray
.
One caveat is that you might want to provide your own insert_or_assign
function, unless you can use C++17 (see this answer). Also, you need to typedef
your types to prevent certain build errors. Once you figure out how to use std::map
, iterators etc., it is pretty straightforward and fast.
참고URL : https://stackoverflow.com/questions/376090/nsdictionary-with-ordered-keys
'IT TIP' 카테고리의 다른 글
adapter-Any real example of Adapter Pattern (0) | 2020.10.13 |
---|---|
VBA를 사용하여 파일이 있는지 확인하십시오. (0) | 2020.10.13 |
ArrayBlockingQueue에서 최종 멤버 필드를 로컬 최종 변수에 복사하는 이유는 무엇입니까? (0) | 2020.10.12 |
Node.js 애플리케이션에 대한 권한 부여 접근 방식 및 디자인 패턴 (0) | 2020.10.12 |
왜 pom.xml의 modelVersion이 필요하고 항상 4.0.0으로 설정됩니까? (0) | 2020.10.12 |