zoukankan      html  css  js  c++  java
  • 数字/字符排序及数据遍历快慢探究

    enumerateObjectsUsingBlock、ForLoop、ForIn、EnumerateObjectsWithOptions PK

    0. viewDidLoad中调用函数

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        //数字排序
        [self numberSort];
        
        //字符排序
        [self charSort];
       
        //遍历数组快慢 enumerateObjectsUsingBlock ForLoop ForIn
        [self ForLoopAndForInAndEnumerateObjectsUsingBlock];
        
        //通过Value查找Index快慢 ForIn EnumerateObjectsUsingBlock EnumerateObjectsWithOptions
        [self ForInAndEnumerateObjectsUsingBlockAndEnumerateObjectsWithOptions];
        
        //遍历字典快慢 ForIn enumerateKeysAndObjectsUsingBlock
        [self ForInAndEnumerateKeysAndObjectsUsingBlock];
        
        //数组的遍历 enumerateObjectsUsingBlock enumerateObjectsAtIndexes
        [self enumArrayWithEnumBlockAndEnumIndexes];
    }
    

    1. 数字、字符比较排序

    #pragma mark 比较/排序
    #pragma mark - 字符排序 -
    - (void)charSort {
       
        UILabel *lable = [[UILabel alloc] initWithFrame:CGRectMake(10, 120, kDeviceWidth - 20, 50)];
        lable.backgroundColor = [UIColor greenColor];
        lable.numberOfLines = 0;
        [self.view addSubview:lable];
        
        
        NSArray *charArray = @[@"home",@"data",@"date",@"hello",@"key",@"jack"];
        
        /*
         对于NSStringCompareOptions,看看系统的说明:
         
         enum{
         NSCaseInsensitiveSearch = 1,//不区分大小写比较
         NSLiteralSearch = 2,//区分大小写比较
         NSBackwardsSearch = 4,//从字符串末尾开始搜索
         NSAnchoredSearch = 8,//搜索限制范围的字符串
         NSNumbericSearch = 64//按照字符串里的数字为依据,算出顺序。例如 Foo2.txt < Foo7.txt < Foo25.txt
         //以下定义高于 mac os 10.5 或者高于 iphone 2.0 可用
         ,
         NSDiacriticInsensitiveSearch = 128,//忽略 "-" 符号的比较
         NSWidthInsensitiveSearch = 256,//忽略字符串的长度,比较出结果
         NSForcedOrderingSearch = 512//忽略不区分大小写比较的选项,并强制返回 NSOrderedAscending 或者 NSOrderedDescending
         //以下定义高于 iphone 3.2 可用
         ,
         NSRegularExpressionSearch = 1024//只能应用于 rangeOfString:..., stringByReplacingOccurrencesOfString:...和 replaceOccurrencesOfString:... 方法。使用通用兼容的比较方法,如果设置此项,可以去掉 NSCaseInsensitiveSearch 和 NSAnchoredSearch
         }
         */
        NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch|NSNumericSearch|
        NSWidthInsensitiveSearch|NSForcedOrderingSearch;
        NSComparator sort = ^(NSString *obj1,NSString *obj2){
            NSRange range = NSMakeRange(0,obj1.length);
            return [obj1 compare:obj2 options:comparisonOptions range:range];
        };
        NSArray *resultArray2 = [charArray sortedArrayUsingComparator:sort];
    //    NSLog(@"字符串数组排序结果%@",resultArray2);
        
        
        NSMutableString *muStr = [NSMutableString string];
        [muStr appendString:@"(2) 字符串数组排序结果:
    "];
        for (NSString *str in resultArray2) {
            [muStr appendFormat:@"%@ -",str];
        }
        
        lable.text = muStr;
        
    }
    
    #pragma mark - 数字排序 -
    - (void)numberSort {
        
        
        UILabel *lable = [[UILabel alloc] initWithFrame:CGRectMake(10, 50, kDeviceWidth - 20, 50)];
        lable.backgroundColor = [UIColor greenColor];
        lable.numberOfLines = 0;
        [self.view addSubview:lable];
        
        
        NSArray *originalArray = @[@"1",@"21",@"12",@"11",@"0"];
        //block比较方法,数组中可以是NSInteger,NSString(需要转换)
        NSComparator finderSort = ^(id string1,id string2){
            
            if ([string1 integerValue] > [string2 integerValue]) {
                return (NSComparisonResult)NSOrderedDescending;
            }else if ([string1 integerValue] < [string2 integerValue]){
                return (NSComparisonResult)NSOrderedAscending;
            }
            else
                return (NSComparisonResult)NSOrderedSame;
        };
        
        //数组排序:
        NSArray *resultArray = [originalArray sortedArrayUsingComparator:finderSort];
    //    NSLog(@"第一种排序结果:%@",resultArray);
        NSMutableString *muStr = [NSMutableString string];
        [muStr appendString:@"(1) 数字排序结果:
    "];
        for (NSString *str in resultArray) {
            [muStr appendFormat:@"%@ -",str];
        }
        
        lable.text = muStr;
    
        
    }
    

     2. 遍历快慢

    #pragma mark - 遍历字典快慢 -
    - (void)ForInAndEnumerateKeysAndObjectsUsingBlock {
        
        NSMutableDictionary *testDictionary = [NSMutableDictionary dictionary];
        
        for (int i = 0; i < 1000; i++) {
            
            NSString *valueStr = [NSString stringWithFormat:@"jack%04d",i];
            NSString *keyStr = [NSString stringWithFormat:@"name%04d",i];
            [testDictionary setValue:valueStr forKey:keyStr];
        }
        
    //    NSLog(@"==========  %@",testDictionary);
        
        
        //For - in
        NSMutableArray *forInArry = [NSMutableArray array];
        double date_s = CFAbsoluteTimeGetCurrent();
        NSArray *keys = [testDictionary  allKeys];
        for (NSString *key in keys) {
            NSString *Value = testDictionary[key];
            [forInArry addObject:Value];
        }
        double date_current = CFAbsoluteTimeGetCurrent() - date_s;
        NSLog(@" For-in Time: %f ms",date_current * 1000);
        
        //enumerateKeysAndObjectsUsingBlock
        date_s = CFAbsoluteTimeGetCurrent();
        NSMutableArray *enumArry = [NSMutableArray array];
        [testDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
            [enumArry addObject:obj];
        }];
        date_current = CFAbsoluteTimeGetCurrent() - date_s;
        NSLog(@" enumerateBlock Time: %f ms",date_current * 1000);
        
        //enumerateKeysAndObjectsWithOptions
        date_s = CFAbsoluteTimeGetCurrent();
        NSMutableArray * enumOptionArr = [NSMutableArray array];
        [testDictionary enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id  _Nonnull key, NSString   *obj, BOOL * _Nonnull stop) {
            
            [enumOptionArr addObject:obj];
            
        }];
        date_current = CFAbsoluteTimeGetCurrent() - date_s;
        NSLog(@"enumerateOptions Time: %f ms",date_current * 1000);
        
        
    //    NSLog(@"ForInArr: %@",forInArry);
    //    NSLog(@"enumArry: %@",enumArry);
    //    NSLog(@"enumOptionArr: %@",enumOptionArr);
        
       /*
        输出结果:
        For-in Time: 0.099003 ms
        enumerateBlock Time: 0.070989 ms
        enumerateOptions Time: 0.105023 ms
        
        enumerateBlock更快
        结论:
        当我们想遍历字典类型的时候, 推荐使用enumerateBlock(经测试:大量数据enumerateBlock更快,若数据量较小For-in更快)
        */
        
    }
    
    
    #pragma mark - 通过Value查找Index快慢 -
    - (void)ForInAndEnumerateObjectsUsingBlockAndEnumerateObjectsWithOptions {
        
        NSMutableArray *test = [NSMutableArray array];
        for (int i = 0; i < 10000000; i ++) {
            [test addObject:@(i + 10)];
        }
        
        //For-in
        __block NSInteger index = 0;
        double date_s = CFAbsoluteTimeGetCurrent();
        for (NSNumber *num in test) {
            if ([num integerValue] == 9999999) {
                index = [test indexOfObject:num];
                break;
            }
        }
        double date_current = CFAbsoluteTimeGetCurrent() - date_s;
        NSLog(@"index : %ld For-in Time: %f ms",(long)index,date_current * 1000);
        
        //enumerateObjectsUsingBlock
        index = 0;
        date_s = CFAbsoluteTimeGetCurrent();
        [test enumerateObjectsUsingBlock:^(id num, NSUInteger idx, BOOL *stop) {
            if ([num integerValue] == 9999999) {
                index = idx;
                *stop = YES;
            }
        }];
        date_current = CFAbsoluteTimeGetCurrent() - date_s;
        NSLog(@"index : %ld enumerateBlock Time: %f ms",(long)index,date_current * 1000);
        
        //enumerateObjectsWithOptions
        index = 0;
        date_s = CFAbsoluteTimeGetCurrent();
        [test enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id num, NSUInteger idx, BOOL *stop) {
            if ([num integerValue] == 9999999) {
                index = idx;
                *stop = YES;
            }
        }];
        date_current = CFAbsoluteTimeGetCurrent() - date_s;
        NSLog(@"index : %ld enumerateObjectsWithOptions Time: %f ms",(long)index,date_current * 1000);
        /*
         输出结果:
         index : 9999989 For-in Time: 572.869003 ms
         index : 9999989 enumerateBlock Time: 439.854980 ms
         index : 9999989 enumerateObjectsWithOptions Time: 279.659986 ms
         
         enumerateObjectsWithOptions方法最快
         结论:
         通过Value查询index的时候, 面对大量的数组推荐使用 enumerateObjectsWithOptions的并行方法.
         For-in和enumerateObjectsWithOptions方法这里我比较喜欢第二种写法简洁直观.
         */
    }
    
    #pragma mark - 遍历数组快慢 -
    - (void)ForLoopAndForInAndEnumerateObjectsUsingBlock {
        
        NSMutableArray *muArrM = [NSMutableArray array];
        for (int i = 0; i < 1000000; i++) {
            [muArrM addObject:@(i)];
        }
        
        __block int sum = 0;
        double date_s = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < muArrM.count; i++) {
            sum += [muArrM[i] integerValue];
        }
        
        double date_current = CFAbsoluteTimeGetCurrent() - date_s;
        NSLog(@"Sum : %d forLoop Time : %f ms",sum, date_current * 1000);
        
        sum = 0;
        date_s = CFAbsoluteTimeGetCurrent();
        for (NSNumber *num in muArrM) {
            sum += [num integerValue];
        }
        date_current = CFAbsoluteTimeGetCurrent() - date_s;
        NSLog(@"Sum : %d ForIn Time: %f ms",sum, date_current * 1000);
    
        
        sum = 0;
        date_s = CFAbsoluteTimeGetCurrent();
        [muArrM enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            
            sum += [obj integerValue];
        }];
        
        date_current = CFAbsoluteTimeGetCurrent() - date_s;
        NSLog(@"Sum: %d enumrateBlock Time:%f ms", sum, date_current * 1000);
        
        /*
         输出结果:
         Sum : 1783293664 forLoop Time : 30.366004 ms
         Sum : 1783293664 ForIn Time: 13.710976 ms
         Sum: 1783293664 enumrateBlock Time:44.068038 ms
         For-in方法最快速
         结论:
         当只是遍历一个数组的时候使用ForIn会比较快速, 推荐使用For-in遍历数组.
         */
        
    }
    

     3. 数组的遍历

    #pragma mark - enumArrayWithEnumBlockAndEnumIndexes -
    - (void)enumArrayWithEnumBlockAndEnumIndexes {
        
        //对数组中元素块操作
        NSArray* array = @[@"aa",@"bb",@"cc",@"dd",@"ee",@"ff",@"gg"];
        [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            NSLog(@"%@ - %lu",obj,idx);
        }];
        NSLog(@"-----enumerateObjectsUsingBlock--------- ");
        //NSIndexSex 是取值范围 (NSMakeRange(1, 4)前面数字代表从哪个位置开始取,后面数字代表取的长度)
        //options为NSEnumerationReverse倒序,NSEnumerationConcurrent正序
        [array enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 4)] options:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            NSLog(@"%@ - %lu",obj, idx);
        }];
        NSLog(@"-----enumerateObjectsAtIndexes--------- ");
      
    }
    

    enumerateObjectsUsingBlock VS for(... in ...)

     for(... in ...)用起来非常方便、简洁,同时 enumerateObjectsUsingBlock: 也有很多新特性:

    • 通常enumerateObjectsUsingBlock: 和 (for(... in ...)在效率上基本一致,有时会快些。主要是因为它们都是基于 NSFastEnumeration 实现的. 快速迭代在处理的过程中需要多一次转换,当然也会消耗掉一些时间. 基于Block的迭代可以达到本机存储一样快的遍历集合. 对于字典同样适用,而数组的迭代却不行。

    • 注意"enumerateObjectsUsingBlock" 修改局部变量时, 你需要声明局部变量为 __block 类型.

    • enumerateObjectsWithOptions:usingBlock: 支持并发迭代或反向迭代,并发迭代时效率也非常高.

    • 对于字典而言, enumerateObjectsWithOptions:usingBlock 也是唯一的方式可以并发实现恢复Key-Value值.

  • 相关阅读:
    [工具推荐]005.Axure RP Pro 7.0模拟C#TAB控件
    [安卓基础] 008.Android中的显示单位
    [JavaWeb基础] 008.Spring初步配置
    [批处理教程之Shell]002.Linux 常用命令大全
    [注]新手学习编程的最佳方式是什么?
    [C#打包部署教程]001.VS2012 + InstallShield
    [站点推荐]001.学习新技能的37个最佳网站(The 37 Best Websites To Learn Something New)
    程序员如何像写代码一样找女朋友
    [工具-006] C#如何模拟发包登录
    [Linux系统] (1)常用操作(CentOS 7.x)
  • 原文地址:https://www.cnblogs.com/GJ-ios/p/5852140.html
Copyright © 2011-2022 走看看