आदेशित कुंजियों के साथ NS सहकर्मी


81

मेरे पास एक NS सहाल (एक मुट्ठी में संग्रहीत) है जो मैं मूल रूप से एक साहचर्य सरणी (कुंजियों और मूल्यों के रूप में तार) के रूप में उपयोग कर रहा हूं। मैं अपने एप्लिकेशन के हिस्से के रूप में कुंजियों के सरणी का उपयोग करना चाहता हूं, लेकिन मैं उन्हें एक विशिष्ट क्रम में रखना चाहता हूं (वास्तव में ऐसा आदेश नहीं है कि मैं उन्हें टाइप करने के लिए एक एल्गोरिथ्म लिख सकता हूं)। मैं हमेशा कुंजियों के एक अलग सरणी को संग्रहीत कर सकता था, लेकिन यह एक प्रकार की कुटिलता लगती है क्योंकि मुझे हमेशा शब्दकोश की कुंजियों के साथ-साथ सरणी के मानों को भी अपडेट करना होगा, और सुनिश्चित करें कि वे हमेशा मेल खाते हों। वर्तमान में मैं सिर्फ [mydirectory allKeys] का उपयोग करता हूं, लेकिन जाहिर है कि यह उन्हें एक अनियंत्रित, गैर-गारंटीकृत क्रम में लौटाता है। क्या उद्देश्य-सी में एक डेटा संरचना है जो मुझे याद आ रही है? क्या किसी के पास कोई सुझाव है कि कैसे और अधिक सुरुचिपूर्ण ढंग से ऐसा किया जाए?

जवाबों:


23

कुंजी से संबद्ध NSMutableArray होने का समाधान इतना बुरा नहीं है। यह एनएसबर्ड को उप-वर्ग से बचा जाता है, और यदि आप एक्सेस लिखने वालों से सावधान हैं, तो इसे सिंक्रनाइज़ रखना बहुत मुश्किल नहीं होना चाहिए।


2
एक नुकसान यह है कि NS (Mutable) शब्दकोश कुंजी की प्रतियां बनाता है, इसलिए कुंजी सरणी में ऑब्जेक्ट अलग-अलग होंगे। यह समस्याग्रस्त हो सकता है यदि एक कुंजी को उत्परिवर्तित किया जाए।
क्विन टेलर

1
यह एक अच्छा बिंदु है, लेकिन अगर उनके भीतर वस्तुओं को बदलने के बजाय सरणी से ऑब्जेक्ट को जोड़ने और हटाने के लिए उत्परिवर्तन प्रतिबंधित है, तो इसे कम कर दिया जाता है।
अबिज़र्न

1
सुनिश्चित नहीं हैं कि आप किसी ऐसे व्यक्ति को कैसे कुंजीबद्ध करना प्रतिबंधित करेंगे जिसके लिए उन्होंने पहली जगह में एक संकेतक प्रदान किया था। सरणी बस उस कुंजी को एक पॉइंटर स्टोर करती है, और यह नहीं जानती है कि यह बदलता है या नहीं। यदि कुंजी बदली गई है, तो आप सरणी में से जोड़े गए प्रविष्टि को बिल्कुल भी हटाने में सक्षम नहीं हो सकते हैं, जो कि एक वास्तविक सिंक्रनाइज़ेशन समस्या हो सकती है यदि आप सरणी को कुंजी रखते हैं जो अब शब्दकोश में नहीं है, या इसके विपरीत ...: -)
क्विन टेलर

2
BTW, मेरी क्षमा याचना अगर मैं गंभीर रूप से लगता है। मैं खुद इसी समस्या से जूझ रहा हूं, लेकिन चूंकि यह एक रूपरेखा के लिए है, इसलिए मैं इसे डिजाइन करने की कोशिश कर रहा हूं ताकि यह मजबूत हो और हर बोधगम्य स्थिति में सही हो। आप सही हैं कि एक अलग सरणी इतनी बुरी नहीं है , लेकिन यह एक वर्ग की तरह सरल नहीं है जो इसे आपके लिए ट्रैक करता है। इसके अलावा, ऐसे कई लाभ हैं यदि ऐसी कक्षा NS (Mutable) शब्दकोश का विस्तार करती है, क्योंकि इसका उपयोग कहीं भी किया जा सकता है कोको शब्दकोश की आवश्यकता है।
क्विन टेलर

1
मुझे चर्चा में कोई आपत्ति नहीं है। मेरा सुझाव सिर्फ एक समाधान था। एक रूपरेखा लिखना पूरी तरह से एक अलग प्रस्ताव है और यह एक ऐसी चीज है जिसके बारे में सावधानीपूर्वक विचार करने की आवश्यकता है। व्यक्तिगत रूप से, मुझे इस कारण से उत्परिवर्तन में परेशानी होती है, और मैं अपने स्वयं के कार्यक्रमों में उन वर्गों के उपयोग को कम करने की कोशिश करता हूं।
अबिज़र्न

19

मैं एक वास्तविक जवाब के साथ खेल के लिए देर से हूं, लेकिन आपको CHOrderedDictionary की जांच करने में रुचि हो सकती है । यह NSMutableDictionary का एक उपवर्ग है जो कुंजी क्रम बनाए रखने के लिए एक और संरचना को एन्क्रिप्ट करता है। (यह CHDataStructures.framework का हिस्सा है ।) मुझे लगता है कि यह एक शब्दकोश और सरणी को अलग से प्रबंधित करने से अधिक सुविधाजनक है।

प्रकटीकरण: यह ओपन-सोर्स कोड है जो मैंने लिखा था। बस उम्मीद है कि यह इस समस्या का सामना कर रहे दूसरों के लिए उपयोगी हो सकता है।


1
+1 - अभी तक इसे आज़माया नहीं गया है, लेकिन डॉक्स के माध्यम से देखा गया है और ऐसा लगता है कि आपने यहाँ कुछ अच्छा काम किया है। मुझे लगता है कि यह थोड़ा शर्मनाक है कि Apple इनमें से कई बुनियादी बातों को याद कर रहा है।
व्हाइटनीलैंड

मुझे नहीं लगता कि यह शर्मनाक है, यह सिर्फ एक सवाल है कि वे अपने ढांचे को कैसे विकसित करना चाहते हैं। विशेष रूप से, नए वर्गों को फाउंडेशन में शामिल करने के लिए बहुत अधिक मूल्य जोड़ना होगा। ऐसा नहीं है कि किसी शब्दकोश को कुंजियों के क्रमबद्ध सरणी के साथ जोड़ा जाना जटिल है, और Apple सामान के साथ ओवरबोर्ड न जाकर फ्रेमवर्क के आकार (और स्थिरता) को रखने की कोशिश करता है जो कुछ लोग उपयोग कर सकते हैं।
क्विन टेलर

3
यह सिर्फ इतना ही नहीं है कि एक आदेश दिया गया शब्दकोश गायब है, यह है कि इतने उपयोगी CS101 संग्रह गायब हैं। मेरा मानना ​​है कि ऑब्जेक्टिव-सी एप्पल के बिना एक व्यापक रूप से सफल भाषा होगी, सी, सी ++, जावा, सी # के विपरीत, जो अपने रचनाकारों के दायरे से बाहर कई बार सफल साबित हुए हैं।
व्हाइटनीलैंड

1
यह। है। बहुत बढ़िया। शर्म करो मैंने अब तक इस ढांचे की खोज नहीं की थी। यह भविष्य की अधिकांश परियोजनाओं में एक मुख्य आधार होने वाला है। आपका बहुत बहुत धन्यवाद!
देव कंचन

यदि कुंजी एक NSString है, तो क्या यह निम्नलिखित करने के लिए एक समस्या होगी? एक डिक्शनरी बनाने के साथ-साथ एक अरै भी बना सकते हैं और डेटा को जोड़ने और हटाने की एक सामान्य विधि है। सरणी में NSString कुंजियों की सूची है (इच्छित क्रम में) शब्दकोश में NSString कुंजियाँ और मान शामिल हैं
user1046037

15

ऐसी कोई इनबिल्ट विधि नहीं है जिससे आप इसे हासिल कर सकें। लेकिन आपके लिए एक साधारण तर्क काम करता है। आप शब्दकोश तैयार करते समय प्रत्येक कुंजी के सामने कुछ संख्यात्मक पाठ जोड़ सकते हैं। पसंद

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]; 

अब अगर आप छँटाई का उपयोग कर सकते हैं। जबकि आप के रूप में एक ही क्रम में सभी चाबियाँ मिल रहा है।

NSArray *arr =  [[dict allKeys] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];

उस स्थान पर जहां आप उइव्यू में चाबियाँ प्रदर्शित करना चाहते हैं, बस सामने वाले 3 वर्ण को काट दें।


इससे पता चलता है कि पहले तीन वर्णों को कैसे हटाया जाए: stackoverflow.com/questions/1073872/…
लियोन

7

यदि आप एनएसबेल उपवर्ग में जा रहे हैं, तो आपको इन विधियों को न्यूनतम के रूप में लागू करने की आवश्यकता है:

  • एन.एस.
    • -count
    • -objectForKey:
    • -keyEnumerator
  • NSMutableDictionary
    • -removeObjectForKey:
    • -setObject:forKey:
  • NSCopying / NSMutableCopying
    • -copyWithZone:
    • -mutableCopyWithZone:
  • NSCoding
    • -encodeWithCoder:
    • -initWithCoder:
  • NSFastEnumeration (तेंदुए के लिए)
    • -countByEnumeratingWithState:objects:count:

आप जो चाहते हैं उसे करने का सबसे आसान तरीका NSMutablelife का एक उपवर्ग बनाना है, जिसमें उसके स्वयं के NSMutableDictionary है कि यह हेरफेर करता है और चाबियों का एक सेट सेट संग्रहीत करने के लिए एक NSMutableArray है।

यदि आप कभी भी अपनी वस्तुओं को एनकोड नहीं करने जा रहे हैं तो आप लागू करने योग्य को छोड़ सकते हैं -encodeWithCoder: और-initWithCoder:

ऊपर दिए गए 10 तरीकों में आपकी सभी विधि कार्यान्वयन या तो सीधे आपके होस्ट किए गए शब्दकोश या आपके आदेशित कुंजी सरणी के माध्यम से जाएंगे।


5
एक और है जो गैर-स्पष्ट है और मुझे फँसाया है - यदि आप NSCoding को लागू करते हैं, तो भी ओवरराइड करते हैं - (कक्षा) classForKeyedArchiver को वापस करने के लिए [स्व वर्ग]। क्लास क्लस्टर्स इसे हमेशा मूल अभिभावक वर्ग को लौटाने के लिए सेट करते हैं, इसलिए जब तक आप इसे नहीं बदलते हैं, उदाहरणों को हमेशा एक एनएस (म्यूटेबल) शब्दकोश के रूप में डिकोड किया जाएगा।
क्विन टेलर

5

मेरा छोटा जोड़: संख्यात्मक कुंजी द्वारा छांटना (छोटे कोड के लिए शॉर्टहैंड नोटेशन का उपयोग करना)

// 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]];
}

3

त्वरित 'एन गंदा:

जब आपको अपना शब्दकोश ("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];
            }
        }

अब, * अनुक्रमणिका ऑब्जेक्ट में सही क्रम में उपयुक्त कुंजियाँ होंगी। ध्यान दें कि इस समाधान के लिए आवश्यक नहीं है कि सभी कुंजी आवश्यक रूप से मौजूद हों, जो कि सामान्य स्थिति है, जिसके साथ हम काम कर रहे हैं ...


सरणी क्रम के लिए सॉर्ट किए गए ArrayUsingSelector के बारे में क्या? डेवलपर
.apple.com/library/ios/documentation/cocoa/Conceptual/…

2

के लिए, स्विफ्ट 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)

2

NSDictionary के एक आदेशित उपवर्ग का न्यूनतम कार्यान्वयन ( https://github.com/nicklockwood/OrderedDictionary पर आधारित )। अपनी आवश्यकताओं के लिए बेझिझक विस्तार करें:

स्विफ्ट 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) }

उद्देश्य सी

@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]);
}

0

मुझे C ++ बहुत पसंद नहीं है, लेकिन एक समाधान जो मैं खुद को अधिक से अधिक उपयोग करके देखता हूं, वह है Objective-C ++ और std::map Standard Template Library से। यह एक ऐसा शब्दकोश है जिसकी कुंजियों को प्रविष्टि पर स्वचालित रूप से सॉर्ट किया जाता है। यह आश्चर्यजनक रूप से अच्छी तरह से स्केलर प्रकार या ऑब्जेक्टिव-सी ऑब्जेक्ट के साथ कुंजी और मान दोनों के रूप में काम करता है।

यदि आपको मान के रूप में एक सरणी शामिल करने की आवश्यकता है, तो std::vectorइसके बजाय बस का उपयोग करें NSArray

एक चेतावनी यह है कि आप अपना स्वयं का insert_or_assignकार्य प्रदान करना चाहते हैं , जब तक कि आप C ++ 17 ( इस उत्तर को देखें ) का उपयोग नहीं कर सकते । साथ ही, typedefकुछ बिल्ड त्रुटियों को रोकने के लिए आपको अपने प्रकारों की आवश्यकता है । एक बार जब आप यह पता लगा लें कि इसका उपयोग कैसे करना है std::map, इत्यादि, यह बहुत सीधा और तेज है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.