当前位置:网站首页>[OC-Foundation框架]---【集合数组】

[OC-Foundation框架]---【集合数组】

2022-07-06 08:50:00 关于小司

OC的集合概述

  • OC的集合类可以用于存储多个数量不相等的对象并可以实现常用的数据结构
  • OC集合大致上可以分为 NSArray,NSSet, NSDictionary三种
  • NSArray,有序可重复的集合
  • ,NSSet 无序不可重复的集合
  • ,NSDictionary 具有映射关系的集合

数组 NSArray 与可变数组 NSMutableArray

  • NSArray提供了类方法和实例方法来创建NSArray,两种方法需要传入的参数基本相似

      类方法以array开头
      实例方法以init开头
    

创建NSArray的几类方法

  • array:创建一个不包含任何元素的空 NSArray。

  • array WithContentsOfFile:/nit With ContentsOfFile::读取文件内容来创建 NSArray

  • array WithObject:/initwithObject: 创建只包含指定元素的 - NSArray。

  • array WithObjects:/initWithObjecti: 创建包含指定的 入 个元素的 NSArray。

        除此之外,还可使用如不简化语法来创建 NSArray对象。
        NSArray *array = @[,]
    

创建代码

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    
    @autoreleasepool {
    
        NSArray* array = [NSArray arrayWithObjects:@"3g",@"Android", @"Ajax", @"XML", @"Swift", nil];
        NSLog(@" 第一个元素 %@", array[0]);
        NSLog(@" 最后一个元素 %@", [array lastObject]);

        //从获取索引为2的元素开始,以及后面三个元素组成的集合
        NSArray *arr1 = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
        NSLog(@" %@", arr1);

        // 获取元素俄在集合的位置
        NSLog(@" 元素Ajax的位置是 : %ld", [array indexOfObject:@"Ajax"]);

        // 获取元素在集合指定范围中的位置
        NSLog(@"在2-5范围Android的位置是 %ld", [array indexOfObject:@"Android"inRange:NSMakeRange(2, 3)]);
        //集合[16654:2344761] 在2-5范围Android的位置是 9223372036854775807
        // 找不到
        // 其实这也是常量NSNotFound的值


        // 追加元素
        // 类似字符串NSArray本身不变,将新返回的NSArray赋值给 array
        array = [array arrayByAddingObject:@"神奇的iOS"];


        // 向数组的最后追加两一个新数组的所有元素
        //类似字符串NSArray本身不变,将新返回的NSArray赋值给 array
        array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"神奇的不省人室222", @"s神奇的复杂化", @"神奇的我", nil]];
        for (int i= 0; i < array.count; i++) {
    
// NSLog(@"%@-", [array objectAtIndex:i]);
            NSLog(@"%@", array[i]);
// 学习了c熟悉第二种数组用法!
        }

// 将数组集合写入文件
        [arr1 writeToFile:@"myFile.txt" atomically:YES];
    }
    return 0;
}

在这里插入图片描述

操作详解

1)遍历集合元素

     objectAtIndex:index或者 array[i]
     推荐使用后者

2)向NSArray后追加元素

   arrayByAddingObject:--追加单个元素
   arrayWithObjexts: 方法将另一个数组的所有元素追加至数组后面

3)值得一提的是 我们NSArray数组是不可变的所以只要是改变数组内部的值的方法都是开辟一个新空间然后把数组指针指向新的数组而不是在旧数组操作

查看NSArray数组的几种操作

  • 查询集合元素在 NSArray 中的索引。
  • 根据索引值取出 NSArray 集合中的元素。
  • 对集合元素整体调用方法。
  • 对 NSArray 集合进行排序。

NSArray 如何判断集合是否包含制定元素

  • 标准只有一条: 这就用到我们之前学习的isEqual方法了当比较返回了YES,才可以认为该NSArray集合包含
    该元素,并不需要两个元素是同一个元素;

NSArray的比较机制

重写isEqual
  • 我们为了验证比较机制 创建一个FKUser对象
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface FKUser : NSObject
@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSString* pass;
- (id) initWithName : (NSString*) aName pass:(NSString*) aPass;
- (void) say:(NSString*) content;
@end

NS_ASSUME_NONNULL_END

#import "FKUser.h"

@implementation FKUser
- (id) initWithName:(NSString *) name pass:(NSString *) pass {
    
    if (self = [super init]) {
    
        self->_name = name;
        self->_pass = pass;
    }
    return self;
}

- (void) say: (NSString*) content {
    
    NSLog(@" %@ 用无敌嗓音大声吼叫道:%@", self.name, content);
}

//重写比较方法,可以比较标准是如果两个FKUSer的name pass相等 即可认为它们相等
- (BOOL) isEqual:(id) other {
    
    if (self == other) {
    
        return YES;
    } else if ([other class] == FKUser .class) {
    
        FKUser* target = (FKUser*)other;
        return [self.name isEqualToString:target.name] &&[self.pass isEqualToString:target.pass];
    }
    return  NO;
}

@end

  • 注意我们自定义了isEqual的标准,重写比较方法,可以比较标准是如果两个FKUSer的name pass相等 即可认为它们相等
测试isEuqal
#import <Foundation/Foundation.h>
#import "FKUser.h"

int main(int argc, const char * argv[]) {
    
    @autoreleasepool {
    
        //创建NSArray对象
        NSArray* array = @[
        [[FKUser alloc] initWithName:@"sun" pass:@"123"],
        [[FKUser alloc] initWithName:@"bai" pass:@"345"],
        [[FKUser alloc] initWithName:@"zhu" pass:@"654"],
        [[FKUser alloc] initWithName:@"tang" pass:@"178"],
        [[FKUser alloc] initWithName:@"niu" pass:@"155"]];

        //查找指定新FKUser对象在集合里的索引
        FKUser* newUser = [[FKUser alloc] initWithName:@"zhu" pass:@"654"];
        NSUInteger pos = [array indexOfObject:newUser];
        NSLog(@" 查找到newUser的位置为 %ld", pos);
    }
    return 0;
}

在这里插入图片描述

  • 我们测试的例子是创建一个 FKUser对象 这个对象虽然不是我们数组里的对象之一 但是它和数组里的某个对象有着相同属性满足重写之后的isEqual方法即可

对NSArray排序

NSArray 提供了三种排序

  • sortedArrayUsingFunction:context::使用排序函数对集合元素进行排序,函数必须返回NSOrderedDescending、NSOrderedAscending、NSorderedSame这些枚举值,用于代表集合元素的大小。该方法返回一个排序好的新NSArray对象。
  • sortedArrayUsingSelector::使用集合元素自身的方法对集合元素进行排序,函数必须返回NSOrderedDescending、NSOrderedAscending、NSorderedSame这些枚举值,用于代表集合元素的大小。该方法返回一个排序好的新NSArray对象。
  • sortedArrayUsingComparator::使用代码块对集合元素进行排序,函数必须返回NSOrderedDescending、NSOrderedAscending、NSorderedSame这些枚举值,用于代表集合元素的大小。该方法返回一个排序好的新NSArray对象。
//----------------------------
// 对NSArray 进行排序
#import <Foundation/Foundation.h>
#import "FKUser.h"

// 定义比较函数 根据对象的intValue进行比较

NSComparisonResult intSort (id num1, id num2, void *context) {
    
    int val1 = [num1 intValue];
    int val2 = [num2 intValue];
    if (val1 < val2) {
    
        return NSOrderedAscending;
    } else if (val1 > val2) {
    
        return NSOrderedDescending;
    } else if (val1 == val2) {
    
        return NSOrderedSame;
    }
    return 0;
}

int main(int argc, const char * argv[]) {
    
    @autoreleasepool {
    
        NSArray *array = @[@"Objective-C", @"C", @"C++", @"Ruby", @"Perl", @"Swift"];

        // 使用集合元素compare方法排序
        array = [array sortedArrayUsingSelector:@selector(compare:)];
        NSLog(@"%@ ", array);

        //初始化一个元素为NSNumber 的NSAarray对象
        NSArray* arr2 = @[
        [NSNumber numberWithInt:20],
        [NSNumber numberWithInt:12],
        [NSNumber numberWithInt:-8],
        [NSNumber numberWithInt:50],
        [NSNumber numberWithInt:19]
        ];

        //使用insort排序
        arr2 = [arr2 sortedArrayUsingFunction:intSort context:nil];
        NSLog(@"%@", arr2);

        // 使用代码块对集合元素进行排序
        NSArray* arr3 = [arr2 sortedArrayUsingComparator:^(id obj1, id obj2){
    
            if ([obj1 intValue] > [obj2 intValue]) {
    
                return NSOrderedDescending;
            } else if ([obj1 intValue] < [obj2 intValue]) {
    
                return NSOrderedAscending;
            }
            return NSOrderedSame;
        }];
        NSLog(@" %@", arr3);
    }
    return 0;
}

在这里插入图片描述

排序注意之处

  • 对于三种排序方法 第2种是我们自己写内部判断标准,
  • 第三种针对块也是自己写内部标准
  • 集合元素本身可以比较大小,而且直接利用集合元素比较大小的方法进行排序的方法称为自然排序;对于通过比较函数或代码块来指定自定义比较规则的方式,则被称为定制排序。

枚举遍历NSArray集合元素

顺逆序枚举

对于 NSArray对象,除了 可根据集 合元素的索引来遍历集合元素之外,还可以调用NSArray 对象的如下两个方法来返回枚举器。

  • objectEnumerator:返回 NSArray 集合的顺序枚举器。
  • reverseObjectEnumerator:返回 NSArray 集合的逆序枚举器
    上面两个方法都返回一个 NSEnumerator 枚举器,该枚举器只包含如下两个方法
    allobjects:获取被枚举集合中的所有元素。
    nextObiect:获取被枚举集合中的下一个元素。
    一般来说,借助 nextObeiat 方法即可对集合元素进行枚举:程序可采用循环不断获取nextObject 方法的返回值,直到该方法的返回值为 nil 结束循环。
// 7.5.4----正逆序枚举
#import <Foundation/Foundation.h>
#import "FKUser.h"
int main( int argc, char* argv[]) {
    
    @autoreleasepool {
    
        // 读取文件 在之前写过的文件
        NSArray *array = [NSArray arrayWithContentsOfFile:@"myFile.txt"];

        // 获取NSArray 的顺序枚举器
        NSEnumerator *en = [array objectEnumerator];
        id object;
        while (object = [en nextObject]) {
    
            NSLog(@"%@", object);
        }


        NSLog(@"获取逆序枚举器");
        en = [array reverseObjectEnumerator];
        while (object = [en nextObject]) {
    
            NSLog(@" %@", object);
        }
    }
}

在这里插入图片描述

快速枚举

快速枚举(for - in)
OC-提供了一种快速枚举的方法来便利集合 使用快速枚举方法遍历集合无需获得集合的长度,也无需根据索引来访问集合元素 即可快速枚举遍历集合的每个元素
语法入下

       for (type variableName in collection) {
             variableName 自动访问每个元素   
             }

type是 集合元素类型 variableName是一个形参名 ,通过快速枚举将自动将集合元素依次赋值给该形参变量

#import <Foundation/Foundation.h>
#import "FKUser.h"
int main( int argc, char* argv[]) {
    
    @autoreleasepool {
    
        NSArray *array = [NSArray arrayWithContentsOfFile:@"myFile.txt"];
        for (id object1 in array) {
    
            NSLog(@"%@", object1);
        }
    }
}

在这里插入图片描述

关于快速枚举

从上面的程序可以看出 使用快速枚举遍历数组元素不需要获得数组长度 也无需根据索引来访问数组元素
本质是(for-each)循环

	for each
	这种循环无需循环条件 无需迭代循环语句 当每个元素都被迭代一次之后 循环自动结束

可变数组(NSMutableArray)

和NSArray不一样的地方

  • NSArray 代表了不可变的集合 一旦NSArray创建成功 程序就不能向集合中添加新的元素,不能删除集合中已有的元素,也不能替换集合元素
  • 注意 NSArray 只是保存了对象的指针,因此NSArray 只保证这些指针变量地址不改变,但指针变量所指向的对象是可以改变的
  • NSMutableArray是NSArray的子类 ,因此它可以作为NSArray使用

新的操作

NSMutableArray代表的是一个集合元素可变的集合,而NSMutableArray底层采用了传统数组来容纳集合元素
因此 创建一个NSMutableArray 集合时可以通过参数指定底层数组的容纳量

NSMutableArray新增的方法

  • 添加集合元素;add开头
  • 删除集合元素 remove开头
  • 替换集合元素 replace开头
  • 对集合本身排序方法 sort开头
    NSMutableArray是NSArray的子类 所以他也有3个排序 注意NSMutableArra是可变数组集合 所以它返回的是本身 (可以认为对集合本身排序)
    NSArray则是 返回一个新的排序好的NSArray对象

NSArray 的KVC 和KVO(此文章不做解释,暂时没有学习到监听有关知识)

NSArray 的KVC

  • NSArray 允许直接对集合中的所哟元素进行整体的KVC编码,NSArray提供了如下两种编码
  • setValue: forKey: 将集合中所有元素指定的key 对应属性或者实例变量设置为value
  • valueForKey: 返回该NSArray集合中所有元素的指定key组成的NSArray对象
#import <Foundation/Foundation.h>
#import "FKUser.h"

// 定义一个函数 把NSArray集合转换为字符串
NSString* NSCollectToString(NSArray *array) {
    
    NSMutableString* result = [NSMutableString stringWithString:@"["];
    for (id obj1 in array) {
    
        [result appendString:[obj1 description]];
        [result appendString:@", "];
    }
    // 获取字符串长度
    NSUInteger len = [result length];

    //弃掉字符串最后的两个字符
    [result deleteCharactersInRange:NSMakeRange(len-2, 2)];
    [result appendString:@"]"];
    return result;
}

int main( int argc, char* argv[]) {
    
    @autoreleasepool {
    
        NSArray *array = @[
            [[FKUser alloc]initWithName:@"sun" pass:@"123"],
            [[FKUser alloc]initWithName:@"bai" pass:@"345"],
            [[FKUser alloc]initWithName:@"zhu" pass:@"654"],
            [[FKUser alloc]initWithName:@"tang" pass:@"178"],
            [[FKUser alloc]initWithName:@"niu" pass:@"155"],
        ];

        // 获取所有集合元素的name属性组成的新集合
        id newArr = [array valueForKey:@"name"];
        NSLog(@"%@", NSCollectToString(newArr));
// for (int i = 0; i < array.count; i++) {
    
// NSLog(@"%@", newArr[i]);
// }

        //对集合的所有元素进行KVC编程
        //对所所有集合元素的name属性改为“新名字’
        [array setValue:@"李育腾" forKey:@"name"];
// NSLog(@"%@", NSCollectToString(array));
        for (int i = 0; i < array.count; i++) {
    
            NSLog(@"%@", array[i]);
        }
    }
}
奇怪的打印

打印结果没有把数组元素本身性质描述出来

  • 打印结果如下的原因是我没有重写关于description方法
    在这里插入图片描述

  • 重写description方法后的结果

  • 在这里插入图片描述

原网站

版权声明
本文为[关于小司]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_61639290/article/details/124988950