NSArray vasitəsilə necə sıralanır?

NSArray üzərində yineleme üçün standart bir deyim axtarıram. Kodum OS X 10.4 + üçün uyğun olmalıdır.

404
14 июня '09 в 17:21 2009-06-14 17:21 Steve McLeod tərəfindən 14 iyun 'da 17:21' da soruşduqda 2009-06-14 17:21
@ 7 cavab

Adətən 10.5 + / iOS üçün üstünlük kodu.

 for (id object in array) { // do something with object } 

Bu [NSFastEnumeration protocol] ( Kakao Referansı ) ilə uyğun gələn bir kolleksiyada obyektlərin sayılması üçün istifadə olunur. Bu yanaşma sürətdə üstünlüyə malikdir, çünki göstəriciləri bir neçə obyektə saxlayır (bir üsul çağırışı ilə əldə edilir) və birbaşa ardıcıllıqla istifadə edərək tampondan keçir. Bu, hər dəfə loop vasitəsilə -objectAtIndex: dən çox daha sürətlidır.

NSEnumerator keçmək üçün texniki olaraq bir for-in loopunu istifadə edə biləcəyinizə baxmayaraq, qeyd NSEnumerator , bu, sürətli sayım sürətinin demək olar ki, bütün üstünlüklərini inkar edir. Bunun səbəbi, NSEnumerator default tətbiqi -countByEnumeratingWithState:objects:count: hər bir zəng ilə tamponda yalnız bir obyekt qoyur.

Bunu radar://6296108 ( radar://6296108 sürətli siyahıya radar://6296108 ), ancaq "Sabit deyil" olaraq qaytarıldı. Bunun səbəbi sürətli siyahıda obyektlərin bir qrupunu saxlayır və sayıcıya yalnız müəyyən bir nöqtə (məsələn, müəyyən bir obyekt aşkar edildikdən və ya bir şərt yerinə yetirildikdən) və siyahıdan istifadə etmək istəyirsinizsə, fasilə dövründən sonra counter, tez-tez bir neçə obyektin atlandığı olur.

OS X 10.6 / iOS 4.0 və daha yüksək səviyyədə kodlaşdırırsanız, dizilər və digər koleksiyonları saymaq üçün blok API istifadə etmək imkanı da var:

 [array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) { // do something with object }]; 

Siz həmçinin -enumerateObjectsWithOptions:usingBlock: istifadə edə bilərsiniz -enumerateObjectsWithOptions:usingBlock:NSEnumerationConcurrent və / və ya NSEnumerationReverse variantları üçün bir arqument kimi keçir.


10.4 və ya daha əvvəl

Pre-10.5 üçün standart idiom NSEnumerator istifadə və loop, məsələn:

 NSEnumerator *e = [array objectEnumerator]; id object; while (object = [e nextObject]) { // do something with object } 

Mən sadə saxlamağı məsləhət görürəm. Bir sıra tipinə bağlanma qeyri-mümkündür, və -objectAtIndex: istifadə sürətlə təxmin edilən artım -objectAtIndex: hər halda 10.5 + tez bir transferlə yaxşılaşmaq üçün. (Tez siyahıda əsas məlumat strukturunda pointer arithmetic istifadə olunur və metod zənginin bir çox hissəsini aradan qaldırır). Erkən optimallaşdırma heç vaxt yaxşı bir fikir deyil - bu, bir problemi həll edən messier koduna gətirib çıxarır ki, bu da sizin darboğazınız deyil .

-objectEnumerator istifadə edərkən asanlıqla başqa bir NSSet kolleksiyaya (məsələn, NSSet , bir NSDictionary və s. Daxil olan düymələrə) keçmək və ya hətta digər kod dəyişiklikləri olmadan array geri qeyd etmək üçün t217> keçid edə bilərsiniz . NSEnumerator bir üsul olduğu NSEnumerator , hər hansı bir NSEnumerator keçə bilər və hətta NSEnumerator də diqqət etməməlidir. Bundan əlavə, NSEnumerator (ən azı Apple kodu ilə təmin olunur) daha çox obyekt olduğu müddətcə siyahıdakı siyahıdan saxlayır, belə ki, avtomatik həyata keçirməli obyektin nə vaxt davam edəcəyi barədə narahat olmayın.

Bəlkə NSEnumerator (ya da sürətli bir numaralandırma), siz onu NSEnumerator bir kolleksiyadan (array və ya başqa) dəyişikliklərdən qoruyan ən vacib şeydir. Nəzərdən obyektlərə daxil olarkən, qəribə istisnalar və ya ayrı-ayrılıqda (problem meydana gəldikdən sonra çox vaxt) baş verə bilər ki, bu da diskarifikasiya üçün dəhşətli ola bilər. Standart deyimlərdən birini istifadə edərək, "pis" davranış var, belə ki, problem (yanlış kodun səbəbi) bir mutasiya meydana gəldikdən sonra növbəti obyektə daxil olmaq istəyəndə dərhal görünür. Proqramlar daha mürəkkəb və çox işıqlı hala gəldikdə və ya hətta üçüncü şəxslərin kodunun dəyişə biləcəyindən asılı olaraq, kövrək sayma kodu getdikcə problemli olur. FTW encapsulation və soyutma !: -)


618
14 июня '09 в 17:27 2009-06-14 17:27 Cavab Quinn Taylor tərəfindən 14 iyun 'da 17:27' də verildi. 2009-06-14 17:27

OS X 10.4.x və əvvəlki üçün:

  int i; for (i = 0; i < [myArray count]; i++) { id myArrayElement = [myArray objectAtIndex:i]; ...do something useful with myArrayElement } 
border=0

OS X 10.5.x (və ya iPhone) və kənarda:

 for (id myArrayElement in myArray) { ...do something useful with myArrayElement } 
119
14 июня '09 в 17:25 2009-06-14 17:25 cavab 14 iyun 'da 17:25' da verildi. 2009-06-14 17:25

Aşağıda testin nəticələri və mənbə kodu (tətbiqdə yinelemələrin sayını təyin edə bilərsiniz). Milisaniyədəki vaxt, və hər bir qeyd 5-10 dəfə testin orta nəticəsidir. Mən, ümumiyyətlə, 2-3 əhəmiyyətli rəqəm dəqiq olduğunu və bundan sonra hər bir run ilə dəyişəcək. Bu,% 1-dən az bir səhv verir. Test iPhone 3G-də maraqlandığı hədəf platforma olaraq baş verdi.

 numberOfItems NSArray (ms) C Array (ms) Ratio 100 0.39 0.0025 156 191 0.61 0.0028 218 3,256 12.5 0.026 481 4,789 16 0.037 432 6,794 21 0.050 420 10,919 36 0.081 444 19,731 64 0.15 427 22,030 75 0.162 463 32,758 109 0.24 454 77,969 258 0.57 453 100,000 390 0.73 534 

Cocoa məlumat dəstləri (NSDictionary, NSArray, NSSet və s.) İşləyib hazırladığı dərslər yaddaş idarəçiliyi, yenidən bölüşdürmə və s. Haqqında narahatlıq vermədən məlumatların idarə olunması üçün çox gözəl bir interfeys təmin edir. Ancaq qiymətə gəlir. Mən NSNrara'dan NSArray istifadə edərək sadə təkrarlamalar üçün üzən bir C-arraydan daha yavaş olacağını düşünürəm, buna görə bəzi testlər etmək qərarına gəldim və nəticə olduqca şok idi! Mən çox pis olmasını gözləmirdim. Qeyd: bu testlər iPhone 3G-də maraqlandığı hədəf platforma görə aparılır.

Bu testdə NSNumbers-dən C float * və NSArray arasında təsadüfi çıxış performansının çox sadə bir müqayisə edim.

Hər bir dizinin məzmununu və onlar mach_absolute_time () ilə istifadə olunan müddətləri ümumiləşdirmək üçün sadə bir loop yaradır. NSMutableArray ortalama 400 dəfə çoxdur! (400 faiz deyil, yalnız 400 dəfə!), daha 40,000% daha çox!).

Sərlövhə:

//Array_Speed_TestViewController.h

// Array sürəti testi

// Mehmet Akten tərəfindən yaradılıb 05/02/2009.

Copyright MSA Visuals Ltd. Bütün hüquqlar qorunur.

 #import <UIKit/UIKit.h> @interface Array_Speed_TestViewController : UIViewController { int numberOfItems; // number of items in array float *cArray; // normal c array NSMutableArray *nsArray; // ns array double machTimerMillisMult; // multiplier to convert mach_absolute_time() to milliseconds IBOutlet UISlider *sliderCount; IBOutlet UILabel *labelCount; IBOutlet UILabel *labelResults; } -(IBAction) doNSArray:(id)sender; -(IBAction) doCArray:(id)sender; -(IBAction) sliderChanged:(id)sender; @end 

İcra:

//Array_Speed_TestViewController.m

// Array sürəti testi

// Mehmet Akten tərəfindən yaradılıb 05/02/2009.

Copyright MSA Visuals Ltd. Bütün hüquqlar qorunur.

  #import "Array_Speed_TestViewController.h" #include <mach/mach.h> #include <mach/mach_time.h> @implementation Array_Speed_TestViewController // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { NSLog(@"viewDidLoad"); [super viewDidLoad]; cArray = NULL; nsArray = NULL; // read initial slider value setup accordingly [self sliderChanged:sliderCount]; // get mach timer unit size and calculater millisecond factor mach_timebase_info_data_t info; mach_timebase_info( machTimerMillisMult = (double)info.numer / ((double)info.denom * 1000000.0); NSLog(@"machTimerMillisMult = %f", machTimerMillisMult); } // pass in results of mach_absolute_time() // this converts to milliseconds and outputs to the label -(void)displayResult:(uint64_t)duration { double millis = duration * machTimerMillisMult; NSLog(@"displayResult: %f milliseconds", millis); NSString *str = [[NSString alloc] initWithFormat:@"%f milliseconds", millis]; [labelResults setText:str]; [str release]; } // process using NSArray -(IBAction) doNSArray:(id)sender { NSLog(@"doNSArray: %@", sender); uint64_t startTime = mach_absolute_time(); float total = 0; for(int i=0; i<numberOfItems; i++) { total += [[nsArray objectAtIndex:i] floatValue]; } [self displayResult:mach_absolute_time() - startTime]; } // process using C Array -(IBAction) doCArray:(id)sender { NSLog(@"doCArray: %@", sender); uint64_t start = mach_absolute_time(); float total = 0; for(int i=0; i<numberOfItems; i++) { total += cArray[i]; } [self displayResult:mach_absolute_time() - start]; } // allocate NSArray and C Array -(void) allocateArrays { NSLog(@"allocateArrays"); // allocate c array if(cArray) delete cArray; cArray = new float[numberOfItems]; // allocate NSArray [nsArray release]; nsArray = [[NSMutableArray alloc] initWithCapacity:numberOfItems]; // fill with random values for(int i=0; i<numberOfItems; i++) { // add number to c array cArray[i] = random() * 1.0f/(RAND_MAX+1); // add number to NSArray NSNumber *number = [[NSNumber alloc] initWithFloat:cArray[i]]; [nsArray addObject:number]; [number release]; } } // callback for when slider is changed -(IBAction) sliderChanged:(id)sender { numberOfItems = sliderCount.value; NSLog(@"sliderChanged: %@, %i", sender, numberOfItems); NSString *str = [[NSString alloc] initWithFormat:@"%i items", numberOfItems]; [labelCount setText:str]; [str release]; [self allocateArrays]; } //cleanup - (void)dealloc { [nsArray release]; if(cArray) delete cArray; [super dealloc]; } @end 

Kimdən: memo.tv

////////////////////

Bloklara girildikdən etibarən mövcud olan bloklar ilə bir sıra yineleyebilirsiniz. Onun sintaksiyası sürətli bir siyahı kimi yaxşı deyil, lakin bir çox maraqlı funksiya var: paralel sayım. Hesablama qaydası vacib deyilsə və vəzifələr blokirovka etmədən paralel olaraq icra edilə bilərsə, bu, çox əsaslı bir sistemdə əhəmiyyətli bir sürətlə təmin edə bilər. Paralel nömrələmə bölməsində bu haqda daha çox məlumat əldə edin.

 [myArray enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) { [self doSomethingWith:object]; }]; [myArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [self doSomethingWith:object]; }]; 

/////////// NSFastEnumerator

Tez bir sayta fikir birləşməni optimallaşdırmaq üçün C arrayə tez bir zamanda istifadə etməkdir. Yalnız ənənəvi NSEnumeratordan daha sürətli olmalı, lakin Objective-C 2.0 da çox qısa bir sintaksis təmin edir.

 id object; for (object in myArray) { [self doSomethingWith:object]; } 

/////////////////

Nsenumerator

Bu xarici yineleme formasıdır: [myArray objectEnumerator] bir obyekt qaytarır. Bu obyektin nüvü qaytarana qədər bir loopda çağırdığımız bir nextObject metodu var

 NSEnumerator *enumerator = [myArray objectEnumerator]; id object; while (object = [enumerator nextObject]) { [self doSomethingWith:object]; } 

/////////////////

objectAtIndex: sayım

Bir tam ədədi artırdıran və [myArray objectAtIndex: index] istifadə edərək bir obyekt istəməsi üçün bir döngə istifadə sayılmanın ən əsas formasıdır.

 NSUInteger count = [myArray count]; for (NSUInteger index = 0; index < count ; index++) { [self doSomethingWith:[myArray objectAtIndex:index]]; } 

////////////// Gönderen: darkdust.net

13
11 мая '14 в 18:30 2014-05-11 18:30 Cavab Hitendra Hckr tərəfindən 11 May 'da 18:30' da verilir 2014-05-11 18:30

Üç yol:

  //NSArray NSArray *arrData = @[@1,@2,@3,@4]; // 1.Classical for (int i=0; i< [arrData count]; i++){ NSLog(@"[%d]:%@",i,arrData[i]); } // 2.Fast iteration for (id element in arrData){ NSLog(@"%@",element); } // 3.Blocks [arrData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"[%lu]:%@",idx,obj); // Set stop to YES in case you want to break the iteration }]; 
  1. İcra etmək üçün ən sürətli yol və 3. yineleyici zərf yazmağı unutma.
7
31 авг. Cavier Calatrava Llavería tərəfindən verilmiş cavab 31 avqust 2015-08-31 10:11 '15 at 10:11 'da 2015-08-31 10:11

NSArray category each metodu əlavə etsəniz çox şey lazımdır.

Kod ObjectiveSugar'dan alındı

 - (void)each:(void (^)(id object))block { [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { block(obj); }]; } 
6
01 янв. Cavab 13 yanvar 01 tarixində verilmişdir 2015-01-01 20:14 '15 'də 20:14' də, 2015-01-01 20:14

İşdə bir dizə dizisini necə elan etdiyini və təkrarlayın:

 NSArray *> 
1
20 июля '16 в 19:54 2016-07-20 19:54 cavab 20 İyun 20, 19:54 1963 2016-07-20 19:54 istifadəçi tərəfindən verilir

Bunu etməyin: -

 for (id object in array) { // statement } 
1
01 июня '17 в 10:17 2017-06-01 10:17 cavabı user8065217 01 iyun 'da 10:17 2017-06-01 10:17 tərəfindən verilir