• 集合类(Objective-C & Swift)


    内容提要:

      本文前两部分讲了Cocoa的集合类和Swift的集合类,其中Cocoa提供的集合类包括NSArray、NSMutableArray、NSDictionary、NSMutableDictionary、NSSet;Swift的集合类包括Array<SomeType>或[SomeType]、Set<SomeType>、Dictionary<KeyType, ValueType>。每个小类目是对应的集合类的用法。最后,本文讲解了Cocoa集合类的3种遍历方法。

    正文内容: 

    一. Cocoa提供的集合类:NSArray、NSMutableArray、NSDictionary、NSMutableDictionary。

       NSArray用来存储对象的有序列表。NSArray类有2个限制:(a)只能存储Objective-C的对象,不能存储基础数据类型,如int、float、enum、struct等。(b)不能在NSArray中存储nil。

       (1)可以在NSArray中放入任意类型的对象。如下所示给array里放入一个NSString对象、一个NSArray对象:

         NSString *aString = @"stringA";
         NSArray *aArray = @[@"A",@"B"];
         NSArray *array = [NSArray arrayWithObjects:aString,aArray, nil];

     (2)NSArray 常用方法:

    //创建数组:
    NSArray *aArray = [NSArray arrayWithObjects:@"A",@"B",@"C",nil];  //结尾有nil
    -(instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag;
    
    //用字面量格式创建数组:
    NSArray *aArray = @[@"A",@"B",@"C"];
    
    //获取包涵的对象个数:
    -(NSUInteger)count;
    
    //获取索引处的对象:
    -(id)objectAtIndex:(NSUInteger)index;
    
    //获取一个object的索引(可以用于判断object是否存在于Array中)第一个方法只要值一致就可以了,第二个方法比较指针一致。
    -(NSUInteger)indexOfObject:(ObjectType)anObject;
    -(NSUInteger)indexOfObjectIdenticalTo:(ObjectType)anObject;
    
    //通过字面量访问数组语法, 获取索引处的对象:
     id myObject = array[i];
    
    //字符串切分成数组
    NSString *string = @"top:bottom:left:right";
    NSArray *array = [string componentsSeparatedByString:@":"];
    
    //数组合并成字符串
    string = [chuncks componentsJoinedByString:@"~"];//得到的字符串是:“top~bottom~left~right”

      (3) 遍历数组

     NSArray *array = @[@"s1", @"s2", @"s3"];
    // 使用快速枚举遍历数组
        for (NSString * string in array) {
            NSLog(@"%@", string);
        }
     //  使用代码块遍历数组
        [array enumerateObjectsUsingBlock:^(NSString *string, NSUInteger index, BOOL *stop){
            NSLog(@"%@", string);
        }];

      快速枚举,执行操作要一项项地线性完成,代码块可以让循环操作并发执行。

    (4)NSMutableArray

        //创建可变数组
        NSMutableArray *array = [NSMutableArray arrayWithCapacity:6];//容量只是一个建议值,是为了让Cocoa能够对代码进行一些优化
    // 或用其它数组创建可变数组
    NSMutableArray *array1 = [NSMutableArray arrayWithArray:array0];
    //在数组末尾添加对象:
        [array addObject:@"myGod"];
        //删除特定索引处的对象:
        [array removeObjectAtIndex:0];//删除后,位于被删除对象后面的元素自动前移补缺

     (5) NSDictionary、NSMutableDictionary

    字典(也被称为散列表或关联数组)使用的是键查询的优化方式。它可以立即找出要查询的数据,而不需要遍历整个数组。

        NSObject *obj1, *obj2, *obj3;
        NSString *key1, *key2, *key3;
    // 创建字典 NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:obj1, key1, obj2, key2, obj3, key3, nil]; //用字面量语法创建字典 NSDictionary *dictionary1 = @{key1:obj1, key2:obj2, key3:obj3}; //使用key访问数值 NSObject *obj = [dictionary objectForKey:key1]; // 使用字面量语法根据key访问数值 NSObject *obj0 = dictionary[key1]; // 创建可变字典 NSMutableDictionary *mutableDictionary1 = [NSMutableDictionary dictionary]; NSMutableDictionary *mutableDictionary2 = [NSMutableDictionary dictionaryWithCapacity:4]; //为字典添加元素 [mutableDictionary1 setObject:obj1 forKey:key1]; //删除元素 [mutableDictionary1 removeObjectForKey:key1];

    二. Swift中的集合类:Array<SomeType>或[SomeType]、Set<SomeType>、Dictionary<KeyType, ValueType>。

      Swift语言中的数组和字典存储的数值类型必须明确。在后台,Swift 的数组和字典都是由泛型集合来实现的。

    (1)数组: Array<SomeType>或[SomeType]

       Objective-C 的 NSArray 和 NSMutableArray ,这两个类可以存储任意类型的对象,并且不提供所返回对象的任何特别信息。在 Swift 中,数据值在被存储进入某个数组之前类型必须明确,方法是通过显式的类型标注或类型推断,可以存储基础数据类型,如Int、Float等。比如Array<SomeType>这样的形式,其中SomeType是这个数组中唯一允许存在的数据类型。

    // 创建数组
    var sList: [String] = ["s1", "s2", "s3"]
    var sList3:[String] = []
    
    // 创建数组(类型推断)
    var sList0 = ["s1", "s2", "s3"]
    
    // 使用构造语法,创建数组
    var someInts = [Int]()
    
    // 使用构造语法,创建特定大小并且所有数据为默认值的数组
    var threeDoubles = [Double](count: 3, repeatedValue:0.0)
    
    // 使用构造语法,创建特定大小并且所有数据为默认值的数组(类型推断)
    var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5)
    
    // 数组中元素个数
    print("The sList contains (sList.count) items")
    
    
    // 判断是否为空
    if sList3.isEmpty {
        print("Empty")
    }else {
        print("Not Empty")
    }
    
    // 在数组后面添加新元素
    sList.append("s4")
    
    //使用加法赋值运算符(+=)在数组后面添加1个或多个新元素
    sList += ["s5"];
    sList += ["s6", "s7", "s8"]
    
    // 使用加号操作符组合两个数组
    var sixDoubles = threeDoubles + anotherThreeDoubles
    
    //使用下标语法来获取数组中的数据项
    var a = sList[0]
    
    //使用下标语法改变对应数据
    sList[0] = "egg"
    
    //使用下标改变一系列数值,个数有可能不同
    sList[2...7] = ["egg", "egg"]//把2-7共5个值替换成了2个值
    
    //插入
    sList.insert("apple", atIndex: 2)
    
    //移除,并返回移除的数值
    let b = sList.removeAtIndex(0)
    
    //移除最后一项
    let last = sList.removeLast()
    //移除所有,[]但不为nil
    sList.removeAll()
    //遍历数组
    for item in sList{
        print(item)
    }

    (2)Set<SomeType>

    Set用来存储相同类型并且没有确定顺序的值,Set中元素顺序不确定,Set中元素不重复。

    //创建特定类型的空Set
    var set0 = Set<Character>()
    
    //Set中元素个数
    print("letters is of type Set<Character> with (set0.count) count")
    
    //赋空值
    set0 = []
    
    //使用数组字面量来构造一个Set
    var set: Set<String> = ["s1", "s2", "s3"]
    
    //使用数组字面量来构造一个Set(类型推断)
    var set1: Set = ["s1", "s2", "s3"]
    
    
    //isEmpty
    if set0.isEmpty {
        print("Empty")
    }else {
        print("Not Empty")
    }
    
    //插入,添加一个新的元素
    set0.insert("a")
    
    //删除一个元素,返回nil或者返回被删除的元素
    let cc = set0.remove("b")
    
    //删除Set中所有值, Set变为空,但不为nil
    set0.removeAll()
    
    //遍历Set
    for value in set1 {
        print("(value)")
    }
    
    let a : Set = [1, 3, 5, 7, 9]
    let b : Set = [0, 2, 4, 6, 8]
    let c : Set = [2, 4]
    
    //union 并集
    a.union(b)
    //intersect 交集
    a.intersect(b)
    //exclusiveOr 并集-交集
    a.exclusiveOr(b)
    //subtract a-b
    a.subtract(b)
    
    // “是否等”运算符(==)
    a == c
    
    //isSubsetOf 是否是子集
    c.isSubsetOf(a)
    
    //isSupersetOf 是否是父集
    a.isSupersetOf(c)
    
    //isStrictSubsetOf 是否是子集 并且不相等(但a == c却是true)
    c.isSubsetOf(a)
    
    //isStrictSupersetOf 是否是父集 并且不相等(但a == c却是true)
    a.isSupersetOf(c)
    
    // a和c没有一个相同的值则为true
    a.isDisjointWith(c)

    (3)Dictionary<KeyType, ValueType>

    KeyType的唯一限制就是可哈希的,这样可以保证它是独一无二的,所有的 Swift 基本类型(例如StringInt, DoubleBool)都是默认可哈希的,并且所有这些类型都可以在字典中当做键使用。(PS:可哈希的,即该类型必须提供一个方法来计算它的哈希值,比如两个对象是否相等,会去比较两个对象的哈希值是否相等)。

    let obj1 : String = "obj1", obj2 : String = "obj2", obj3 : String = "obj3"
    let key1 : String = "key1", key2 : String  = "key2", key3 : String  = "key3"
    
    //创建空字典
    var aDictionary = Dictionary<Int, String>() //值为[:]
    
    //赋值 和使用空字典字面量来 变为空字典
    aDictionary[2] = "Two"
    aDictionary = [:]
    
    //创建字典变量
    var dictionary:[String: String] = [key1:obj1, key2:obj2, key3:obj3]
    
    //创建字典变量(类型推断)
    var dictionary1 = [key1:obj1, key2:obj2, key3:obj3]
    
    //字典的数据项数量
    print("The dictionary contains (dictionary.count) items")
    
    //isEmpty
    if dictionary.isEmpty {
        print("Empty")
    }else {
        print("Not Empty")
    }
    
    //使用下标语法, 添加新的数据项 或 修改老的数据项
    dictionary["key4"] = "obj4"
    dictionary["key1"] = "XX"
    
    // 根据key 设置新的键值对 或 更新已有key的值
    dictionary.updateValue("YY", forKey: "key1")
    
    // updateValue返回值为 key所对应的value值 或者 nil
    let oldValue = dictionary.updateValue("YY", forKey: "ke1")
    
    // 下标语法返回值为 key所对应的value值 或者 nil
    let value = dictionary["k1"]
    
    // 下标语法 赋新值 或者 从字典里移除一个键值对 
    dictionary["key1"] = "XY"
    dictionary["key1"] = nil
    
    // 移除键值对 removeValue返回值为 key所对应的value值 或者 nil
    let removeValue =  dictionary.removeValueForKey("key4")
    
    //字典遍历
    for (key, value) in dictionary {
        print("(key):(value)")
    }
    
    //字典遍历 keys
    for key in dictionary.keys {
        print("(key)")
    }
    
    //字典遍历 values
    for value in dictionary.values {
        print("(value)")
    }
    
    // 使用dictionary的keys或者values 创建新数组Array
    let keysArray = Array(dictionary.keys)
    let valueArray = Array(dictionary.values)

     三. Cocoa中的集合类的遍历

    (1)for循环

    //Array
    for (NSUInteger i = 0; i < Array.count; i++) {
        id object = Array[i]
    }
    //Dictionary
    NSArray *keys = [Dictionary allKeys];
    for (NSUInteger i = 0; i < keys.count; i++) {
        id key = keys[i];
        id object = [Dictionary objectForKey:key];
    }
    //Set
    NSArray *tranArray = [Set allObjects];
    //Then same with array

    (2)Fast Enumeration

    //Array, 反向遍历[array reverseObjectEnumerator]
    for(id object in self.testArray){
    
    }
    
    //Dictionay
    for(id key in self.testDic){
        id object = [self.testDic objectForKey:key];
    }
    
    //Set
    for(id object in self.testSet) {
    
    }

    (3)Block Enumeration

     优点:可以获取index,不用生成中间变量,方便实现反向遍历,对于比较耗时的任务实现并发遍历比较方便,提供停止遍历的变量。

    //Array
    [Array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    
    }];
    
    //Dictionary
    [Dictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
    }];
    
    //Set
    [Set enumerateObjectsUsingBlock:^(id  _Nonnull obj, BOOL * _Nonnull stop) {
    
    }];
    //另一个block遍历方法,以Array为例,Dictionary和Set分别也实现了对应的方法。 //NSEnumerationOptions是一个枚举类型, [Array enumerateObjectsWithOptions:(NSEnumerationOptions) usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { }]; typedef NS_OPTIONS(NSUInteger, NSEnumerationOptions) { NSEnumerationConcurrent = (1UL << 0), //遍历的块并发执行 NSEnumerationReverse = (1UL << 1), //反向遍历 };
  • 相关阅读:
    19、spring注解学习(声明式事务)——spring注解版声明式事务
    Visual C# 2015调用SnmpSharpNet库实现简单的SNMP元素查询
    SNMP协议交互学习-获取udp的udpindatagrams
    LwIP的SNMP学习笔记
    stm32f407使用Keil uV5建立工程日志
    IP unnumbered interface,某个接口不编号,某个接口不分配IP地址
    OSPFv3与OSPFv2协议的比较
    卫星网络-拓扑优化-文献笔记
    卫星轨道相关笔记SGP4
    [20190226]删除tab$记录的恢复6.txt
  • 原文地址:https://www.cnblogs.com/Xylophone/p/5319236.html
Copyright © 2020-2023  润新知