मुझे अपना उल्टा करने की जरूरत है NSArray
।
उदहारण के लिए:
[1,2,3,4,5]
बनना चाहिए: [5,4,3,2,1]
इसे हासिल करने का सबसे अच्छा तरीका क्या है?
मुझे अपना उल्टा करने की जरूरत है NSArray
।
उदहारण के लिए:
[1,2,3,4,5]
बनना चाहिए: [5,4,3,2,1]
इसे हासिल करने का सबसे अच्छा तरीका क्या है?
जवाबों:
किसी सरणी की उलटी प्रतिलिपि प्राप्त करने के लिए, danielpunkass 'समाधान का उपयोग करके देखें reverseObjectEnumerator
।
एक परिवर्तनशील सरणी को उलटने के लिए, आप अपने कोड में निम्न श्रेणी जोड़ सकते हैं:
@implementation NSMutableArray (Reverse)
- (void)reverse {
if ([self count] <= 1)
return;
NSUInteger i = 0;
NSUInteger j = [self count] - 1;
while (i < j) {
[self exchangeObjectAtIndex:i
withObjectAtIndex:j];
i++;
j--;
}
}
@end
यदि आप बिल्ट-इन reverseObjectEnumerator
विधि NSArray
और allObjects
विधि का लाभ उठाते हैं, तो बहुत आसान उपाय है NSEnumerator
:
NSArray* reversedArray = [[startArray reverseObjectEnumerator] allObjects];
allObjects
प्रलेखित हैउन वस्तुओं के साथ एक सरणी लौटाने के रूप किया गया है nextObject
, जिन्हें अभी तक क्रम में नहीं निकाला गया है :
इस सरणी में प्रगणित क्रम में प्रगणक की शेष सभी वस्तुएँ हैं ।
कुछ बेंचमार्क
1. RevObjectEnumerator allObjects
यह सबसे तेज़ विधि है:
NSArray *anArray = @[@"aa", @"ab", @"ac", @"ad", @"ae", @"af", @"ag",
@"ah", @"ai", @"aj", @"ak", @"al", @"am", @"an", @"ao", @"ap", @"aq", @"ar", @"as", @"at",
@"au", @"av", @"aw", @"ax", @"ay", @"az", @"ba", @"bb", @"bc", @"bd", @"bf", @"bg", @"bh",
@"bi", @"bj", @"bk", @"bl", @"bm", @"bn", @"bo", @"bp", @"bq", @"br", @"bs", @"bt", @"bu",
@"bv", @"bw", @"bx", @"by", @"bz", @"ca", @"cb", @"cc", @"cd", @"ce", @"cf", @"cg", @"ch",
@"ci", @"cj", @"ck", @"cl", @"cm", @"cn", @"co", @"cp", @"cq", @"cr", @"cs", @"ct", @"cu",
@"cv", @"cw", @"cx", @"cy", @"cz"];
NSDate *methodStart = [NSDate date];
NSArray *reversed = [[anArray reverseObjectEnumerator] allObjects];
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"executionTime = %f", executionTime);
परिणाम: executionTime = 0.000026
2. मैं एक रिवर्स ऑबजेक्टइंटररेटर पर काम कर रहा हूं
यह 1.5x और 2.5x के बीच धीमा है:
NSDate *methodStart = [NSDate date];
NSMutableArray *array = [NSMutableArray arrayWithCapacity:[anArray count]];
NSEnumerator *enumerator = [anArray reverseObjectEnumerator];
for (id element in enumerator) {
[array addObject:element];
}
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"executionTime = %f", executionTime);
परिणाम: executionTime = 0.000071
3. SortedArrayUsingComparator
यह 30x और 40x धीमी गति के बीच है (यहाँ कोई आश्चर्य नहीं):
NSDate *methodStart = [NSDate date];
NSArray *reversed = [anArray sortedArrayUsingComparator: ^(id obj1, id obj2) {
return [anArray indexOfObject:obj1] < [anArray indexOfObject:obj2] ? NSOrderedDescending : NSOrderedAscending;
}];
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"executionTime = %f", executionTime);
परिणाम: executionTime = 0.001100
तो [[anArray reverseObjectEnumerator] allObjects]
यह स्पष्ट विजेता है जब यह गति और सहजता की बात करता है।
enumerateObjectsWithOptions:NSEnumerationReverse
?
enumerateObjectsWithOptions:NSEnumerationReverse
- शीर्ष एक 0.000072
सेकंड में पूरा किया, सेकंड में ब्लॉक विधि 0.000009
।
दासबुट में सही दृष्टिकोण है, लेकिन उनके कोड में कुछ गलतियां हैं। यहाँ एक पूरी तरह से सामान्य कोड स्निपेट है जो किसी भी NSMutableArray को उल्टा कर देगा:
/* Algorithm: swap the object N elements from the top with the object N
* elements from the bottom. Integer division will wrap down, leaving
* the middle element untouched if count is odd.
*/
for(int i = 0; i < [array count] / 2; i++) {
int j = [array count] - i - 1;
[array exchangeObjectAtIndex:i withObjectAtIndex:j];
}
आप इसे C फ़ंक्शन में या बोनस अंक के लिए रैप कर सकते हैं, इसे NSMutableArray में जोड़ने के लिए श्रेणियों का उपयोग कर सकते हैं। (उस स्थिति में, 'ऐरे' 'स्व' बन जाएगा।) आप चाहें [array count]
तो लूप से पहले एक वैरिएबल को असाइन करके और यदि आप चाहें तो उस वैरिएबल का उपयोग करके इसे ऑप्टिमाइज़ भी कर सकते हैं ।
यदि आपके पास केवल एक नियमित NSArray है, तो इसे रिवर्स करने का कोई तरीका नहीं है, क्योंकि NSArrays को संशोधित नहीं किया जा सकता है। लेकिन आप एक उलटी प्रतिलिपि बना सकते हैं:
NSMutableArray * copy = [NSMutableArray arrayWithCapacity:[array count]];
for(int i = 0; i < [array count]; i++) {
[copy addObject:[array objectAtIndex:[array count] - i - 1]];
}
या एक लाइन में करने के लिए इस छोटी सी ट्रिक का उपयोग करें:
NSArray * copy = [[array reverseObjectEnumerator] allObjects];
यदि आप किसी सरणी पर पीछे की ओर लूप करना चाहते हैं, तो आप for
/ a के in
साथ लूप का उपयोग कर सकते हैं [array reverseObjectEnumerator]
, लेकिन इसका उपयोग करने के लिए थोड़ा अधिक कुशल होने की संभावना है -enumerateObjectsWithOptions:usingBlock:
:
[array enumerateObjectsWithOptions:NSEnumerationReverse
usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
// This is your loop body. Use the object in obj here.
// If you need the index, it's in idx.
// (This is the best feature of this method, IMHO.)
// Instead of using 'continue', use 'return'.
// Instead of using 'break', set '*stop = YES' and then 'return'.
// Making the surrounding method/block return is tricky and probably
// requires a '__block' variable.
// (This is the worst feature of this method, IMHO.)
}];
( नोट : फाउंडेशन के पांच और वर्षों के अनुभव, एक नई उद्देश्य-सी सुविधा या दो, और टिप्पणियों से कुछ सुझाव के साथ 2014 में पर्याप्त रूप से अपडेट किया गया।)
ऊपर दिए गए अन्य उत्तरों की समीक्षा करने के बाद और मैट गैलाघेर की चर्चा यहाँ पा सकते हैं
मैं यह प्रस्ताव करता हूं:
NSMutableArray * reverseArray = [NSMutableArray arrayWithCapacity:[myArray count]];
for (id element in [myArray reverseObjectEnumerator]) {
[reverseArray addObject:element];
}
जैसा कि मैट देखता है:
उपरोक्त मामले में, आप आश्चर्यचकित हो सकते हैं कि - [NSArray रिवर्स ऑबजेक्ट इन्नुमेटर] लूप के प्रत्येक पुनरावृत्ति पर चलाया जाएगा - संभवतः कोड को धीमा कर रहा है। <...>
कुछ ही समय बाद, वह इस प्रकार उत्तर देता है:
<...> "संग्रह" अभिव्यक्ति का मूल्यांकन केवल एक बार किया जाता है, जब लूप शुरू होता है। यह सबसे अच्छा मामला है, क्योंकि आप लूप के प्रति-प्रदर्शन प्रदर्शन को प्रभावित किए बिना एक सुरक्षित फ़ंक्शन को "संग्रह" अभिव्यक्ति में सुरक्षित रूप से डाल सकते हैं।
जॉर्ज शॉली की श्रेणियां बहुत अच्छी हैं। हालाँकि, NSMutableArray के लिए, सूचक के लिए NSUIntegers का उपयोग करने से सरणी रिक्त होने पर क्रैश हो जाता है। सही कोड है:
@implementation NSMutableArray (Reverse)
- (void)reverse {
NSInteger i = 0;
NSInteger j = [self count] - 1;
while (i < j) {
[self exchangeObjectAtIndex:i
withObjectAtIndex:j];
i++;
j--;
}
}
@end
का उपयोग करें enumerateObjectsWithOptions:NSEnumerationReverse usingBlock
। इसके ऊपर @ जोहान्सफारेनक्रग के बेंचमार्क का उपयोग करते हुए, इसने 8x जल्दी पूरा किया [[array reverseObjectEnumerator] allObjects];
:
NSDate *methodStart = [NSDate date];
[anArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
//
}];
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"executionTime = %f", executionTime);
NSMutableArray *objMyObject = [NSMutableArray arrayWithArray:[self reverseArray:objArrayToBeReversed]];
// Function reverseArray
-(NSArray *) reverseArray : (NSArray *) myArray {
return [[myArray reverseObjectEnumerator] allObjects];
}
रिवर्स सरणी और इसके माध्यम से लूपिंग:
[[[startArray reverseObjectEnumerator] allObjects] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
...
}];
मेरे लिए, क्या आपने विचार किया है कि सरणी को पहले स्थान पर कैसे आबाद किया गया था? मैं एक सरणी में MANY ऑब्जेक्ट्स को जोड़ने की प्रक्रिया में था, और किसी भी मौजूदा ऑब्जेक्ट को एक से ऊपर धकेलते हुए शुरुआत में हर एक को सम्मिलित करने का निर्णय लिया। इस मामले में, एक परिवर्तनशील सरणी की आवश्यकता होती है।
NSMutableArray *myMutableArray = [[NSMutableArray alloc] initWithCapacity:1];
[myMutableArray insertObject:aNewObject atIndex:0];
या स्काला-वे:
-(NSArray *)reverse
{
if ( self.count < 2 )
return self;
else
return [[self.tail reverse] concat:[NSArray arrayWithObject:self.head]];
}
-(id)head
{
return self.firstObject;
}
-(NSArray *)tail
{
if ( self.count > 1 )
return [self subarrayWithRange:NSMakeRange(1, self.count - 1)];
else
return @[];
}
इसे करने का एक आसान तरीका है।
NSArray *myArray = @[@"5",@"4",@"3",@"2",@"1"];
NSMutableArray *myNewArray = [[NSMutableArray alloc] init]; //this object is going to be your new array with inverse order.
for(int i=0; i<[myNewArray count]; i++){
[myNewArray insertObject:[myNewArray objectAtIndex:i] atIndex:0];
}
//other way to do it
for(NSString *eachValue in myArray){
[myNewArray insertObject:eachValue atIndex:0];
}
//in both cases your new array will look like this
NSLog(@"myNewArray: %@", myNewArray);
//[@"1",@"2",@"3",@"4",@"5"]
आशा है कि ये आपकी मदद करेगा।
मैं किसी भी विधि से निर्मित नहीं जानता। लेकिन, हाथ से कोडिंग करना बहुत मुश्किल नहीं है। आप जिस सरणी के साथ काम कर रहे हैं, उसके तत्वों को मानते हुए NSNumber पूर्णांक प्रकार की वस्तुएं हैं, और 'गिरफ्तार' NSMutableArray है जिसे आप रिवर्स करना चाहते हैं।
int n = [arr count];
for (int i=0; i<n/2; ++i) {
id c = [[arr objectAtIndex:i] retain];
[arr replaceObjectAtIndex:i withObject:[arr objectAtIndex:n-i-1]];
[arr replaceObjectAtIndex:n-i-1 withObject:c];
}
जब से आप एक NSArray के साथ शुरू करते हैं तब आपको मूल NSArray ('OrigArray') की सामग्री के साथ सबसे पहले उत्परिवर्तित सरणी बनाना होगा।
NSMutableArray * arr = [[NSMutableArray alloc] init];
[arr setArray:origArray];
संपादित करें: ब्रेंट के उत्तर में सुझावों के कारण लूप काउंट में फिक्स्ड n -> n / 2 और NSNumber को अधिक सामान्य आईडी में बदल दिया।
यदि आप सब करना चाहते हैं तो रिवर्स में पुनरावृति है, यह कोशिश करें:
// iterate backwards
nextIndex = (currentIndex == 0) ? [myArray count] - 1 : (currentIndex - 1) % [myArray count];
आप [myArrayCount] एक बार कर सकते हैं और इसे एक स्थानीय चर में सहेज सकते हैं (मुझे लगता है कि यह महंगा है), लेकिन मैं यह भी अनुमान लगा रहा हूं कि कंपाइलर कोड के साथ वही काम करेगा जो ऊपर लिखा गया है।
इसे इस्तेमाल करे:
for (int i = 0; i < [arr count]; i++)
{
NSString *str1 = [arr objectAtIndex:[arr count]-1];
[arr insertObject:str1 atIndex:i];
[arr removeObjectAtIndex:[arr count]-1];
}
यहाँ एक अच्छा मैक्रो है जो NSMutableArray या NSArray के लिए काम करेगा :
#define reverseArray(__theArray) {\
if ([__theArray isKindOfClass:[NSMutableArray class]]) {\
if ([(NSMutableArray *)__theArray count] > 1) {\
NSUInteger i = 0;\
NSUInteger j = [(NSMutableArray *)__theArray count]-1;\
while (i < j) {\
[(NSMutableArray *)__theArray exchangeObjectAtIndex:i\
withObjectAtIndex:j];\
i++;\
j--;\
}\
}\
} else if ([__theArray isKindOfClass:[NSArray class]]) {\
__theArray = [[NSArray alloc] initWithArray:[[(NSArray *)__theArray reverseObjectEnumerator] allObjects]];\
}\
}
बस कॉल का उपयोग करने के लिए: reverseArray(myArray);