原文:http://rypress.com/tutorials/objective-c/data-types/nsarray

NSArray

NSArray 是 Objective-C中最常用的数组类型。存储有序的对象集合, 并且提供方便的排序等接口去操作数据。在效率上面没有sets高,但是存储其中的数据保持有序。

The basic collection classes of the Foundation Framework

像NSSet一样,NSArray是不可变的,所以你无法动态的增删其中的数据。与之对应的NSMutableArray类型可提供动态功能,这个类型我们将在本章的第二小节讨论。

创建数组

不可变数组可以使用@[]的语法来创建。这个语法直到Xcode4.4版本时候才提供使用,所以你可能会在老版本的代码中碰到冗长的arrayWithObjects:方法来创建不可变数组的代码。两者的使用方法如下:

NSArray *germanMakes = @[@"Mercedes-Benz", @"BMW", @"Porsche",
                         @"Opel", @"Volkswagen", @"Audi"];
NSArray *ukMakes = [NSArray arrayWithObjects:@"Aston Martin",
                    @"Lotus", @"Jaguar", @"Bentley", nil];

NSLog(]);
NSLog(]);

正如你所见,不同的数据可以使用中括号加上下标的方式取得或者使用objectAtIndex:去取得。在Xcode4.4之前objectAtIndex:是标准的做法。

枚举数组

款速枚举是最高效的迭代数组的方法,枚举的时候取出的数据保持原有顺序。当然出了快速枚举方式你也可以通过count方法来进行。这是一种比较传统饿做法。

NSArray *germanMakes = @[@"Mercedes-Benz", @"BMW", @"Porsche",
                         @"Opel", @"Volkswagen", @"Audi"];
// With fast-enumeration
for (NSString *item in germanMakes) {
    NSLog(@"%@", item);
}
// With a traditional for loop
; i<[germanMakes count]; i++) {
    NSLog(@"%d: %@", i, germanMakes[i]);
}

如果你非常熟悉块操作的话,你也可以使用enumerateObjectsUsingBlock:方法

[germanMakes enumerateObjectsUsingBlock:^(id obj,
                                          NSUInteger idx,
                                          BOOL *stop) {
    NSLog(@"%ld: %@", idx, obj);
}];

数组比较

数组是之间可以使用isEqualToArray:进行比较,如果返回YES则说明两者相同。

NSArray *germanMakes = @[@"Mercedes-Benz", @"BMW", @"Porsche",
                         @"Opel", @"Volkswagen", @"Audi"];
NSArray *sameGermanMakes = [NSArray arrayWithObjects:@"Mercedes-Benz",
                            @"BMW", @"Porsche", @"Opel",
                            @"Volkswagen", @"Audi", nil];

if ([germanMakes isEqualToArray:sameGermanMakes]) {
    NSLog(@"Oh good, literal arrays are the same as NSArrays");
}

成员检查

NSArray提供了成员的检查方法。containsObject:方法检查当前数组中是否存在某个数据。 indexOfObject:方法则返回所要查找的对象的首次出现index,如果没有则返回NSNotFound。

NSArray *germanMakes = @[@"Mercedes-Benz", @"BMW", @"Porsche",
                         @"Opel", @"Volkswagen", @"Audi"];
// BOOL checking
if ([germanMakes containsObject:@"BMW"]) {
    NSLog(@"BMW is a German auto maker");
}
// Index checking
NSUInteger index = [germanMakes indexOfObject:@"BMW"];
if (index == NSNotFound) {
    NSLog(@"Well that's not quite right...");
} else {
    NSLog(@"BMW is a German auto maker and is at index %ld", index);
}

如前所属,数组中可以存储多个相同的对象,而indexOfObject:只返回首个对象的下标,其实你可以使用 indexOfObject:inRange:方法来进行返回查询。

记住sets类型在成员检查的时候更加高效,所以如果你需要在大量的对象中查找则使用sets会效率更高。

数组排序

排序是数组的一大重要特性。可以通过sortedArrayUsingComparator:方法可以快速的达到这个目的,此方法接受^NSComparisonResult(id obj1, id obj2)块,此块按照下标返回。

Return Value Description
NSOrderedAscending obj1 comes before obj2
NSOrderedSame obj1 and obj2 have no order
NSOrderedDescending obj1 comes after obj2

下面的例子中按照name的长度从短到长排序:

NSArray *germanMakes = @[@"Mercedes-Benz", @"BMW", @"Porsche",
                         @"Opel", @"Volkswagen", @"Audi"];
NSArray *sortedMakes = [germanMakes sortedArrayUsingComparator:
    ^NSComparisonResult(id obj1, id obj2) {
        if ([obj1 length] < [obj2 length]) {
            return NSOrderedAscending;
        } else if ([obj1 length] > [obj2 length]) {
            return NSOrderedDescending;
        } else {
            return NSOrderedSame;
        }
}];
NSLog(@"%@", sortedMakes);

像NSSet一样,NSArray是不可变的,所以排序后其实是新建了一个新的NSArray对象,但是内部的对象还是引用原来的指针。

过滤数组

你可以直接使用filteredArrayUsingPredicate:方法来过滤数组。使用方法参考如下,和sort一样也是生成新的NSArray对象。

NSArray *germanMakes = @[@"Mercedes-Benz", @"BMW", @"Porsche",
                         @"Opel", @"Volkswagen", @"Audi"];

NSPredicate *beforeL = [NSPredicate predicateWithBlock:
    ^BOOL(id evaluatedObject, NSDictionary *bindings) {
        NSComparisonResult result = [@"L" compare:evaluatedObject];
        if (result == NSOrderedDescending) {
            return YES;
        } else {
            return NO;
        }
    }];
NSArray *makesBeforeL = [germanMakes
                         filteredArrayUsingPredicate:beforeL];
NSLog(@"%@", makesBeforeL);    // BMW, Audi

数组分隔

分隔一个数组和使用substrings分隔NSString产不多,当然不是用substringWithRange:而是使用subarrayWithRange:方法爱分隔数组。

NSArray *germanMakes = @[@"Mercedes-Benz", @"BMW", @"Porsche",
                         @"Opel", @"Volkswagen", @"Audi"];

NSArray *lastTwo = [germanMakes subarrayWithRange:NSMakeRange(, )];
NSLog(@"%@", lastTwo);    // Volkswagen, Audi

组装数组

数组可以通过arrayByAddingObjectsFromArray:方法进行组合。和之前讨论一样的这会新建一个数组。

NSArray *germanMakes = @[@"Mercedes-Benz", @"BMW", @"Porsche",
                         @"Opel", @"Volkswagen", @"Audi"];
NSArray *ukMakes = @[@"Aston Martin", @"Lotus", @"Jaguar", @"Bentley"];

NSArray *allMakes = [germanMakes arrayByAddingObjectsFromArray:ukMakes];
NSLog(@"%@", allMakes);

String化

componentsJoinedByString:方法将数组内的元素都转化成string,元素之间使用指定的符号进行分隔。

NSArray *ukMakes = @[@"Aston Martin", @"Lotus", @"Jaguar", @"Bentley"];
NSLog(@"%@", [ukMakes componentsJoinedByString:@", "]);

NSMutableArray可变数组

NSMutableArray类可以定义动态的增删数据的可以数组对象。在效率上来说这比set和字典的增删慢很多。

创建可变数组

通过列举元素来创建的数组都是不可变的,最简单的创建可变数组是使用arrayWithObjects:方法,详见如下:

NSMutableArray *brokenCars = [NSMutableArray arrayWithObjects:
                              @"Audi A6", @"BMW Z3",
                              @"Audi Quattro", @"Audi TT", nil];

你可以通过array 或者arrayWithCapacity:创建一个空的可变数组。如果你已经有了有一个不可变数组但是你想将其转化成一个可变数组的话,你可以使用arrayWithArray:方法。

元素的增删

addObject: 和 removeLastObject方法是两个最基本的操作数组元素的方法。这两个方法都是对数组最后的元素产生影响,所以我们甚至可以通过他们来达到栈的效果。

NSMutableArray *brokenCars = [NSMutableArray arrayWithObjects:
                              @"Audi A6", @"BMW Z3",
                              @"Audi Quattro", @"Audi TT", nil];
[brokenCars addObject:@"BMW F25"];
NSLog(@"%@", brokenCars);       // BMW F25 added to end
[brokenCars removeLastObject];
NSLog(@"%@", brokenCars);       // BMW F25 removed from end

他们是最高效的增加和删除数组最后元素的方法,但是你可以通过insertObject:atIndex: 和 removeObjectAtIndex:方法使用随意的则数组某个位置增加或者删除元素。如果你不知道某个元素的具体位置的时候你可以使用removeObject:方法来直接删除,这其实是indexOfObject:然后removeObjectAtIndex:相结合的方法。

// Add BMW F25 to front
[brokenCars insertObject:];
// Remove BMW F25 from front
[brokenCars removeObjectAtIndex:];
// Remove Audi Quattro
[brokenCars removeObject:@"Audi Quattro"];

也可以通过replaceObjectAtIndex:withObject:方法来替换体质下标的元素。

// Change second item to Audi Q5
[brokenCars replaceObjectAtIndex: withObject:@"Audi Q5"];

Sorting With Descriptors

Inline sorts can be accomplished through sortUsingComparator:, which works just like the immutable version discussed in Sorting Arrays. However, this section discusses an alternative method for sorting arrays called NSSortDescriptor. Sort descriptors typically result in code that is more semantic and less redundant than block-based sorts.

The NSSortDescriptor class encapsulates all of the information required to sort an array of dictionaries or custom objects. This includes the property to be compared, the comparison method, and whether the sort is ascending or descending. Once you configure a descriptor(s), you can sort an array by passing it to the sortUsingDescriptors:method. For example, the following snippet sorts an array of cars by price and then by model.

NSDictionary *car1 = @{
    @"make": @"Volkswagen",
    @"model": @"Golf",
    @"price": [NSDecimalNumber decimalNumberWithString:@"18750.00"]
};
NSDictionary *car2 = @{
    @"make": @"Volkswagen",
    @"model": @"Eos",
    @"price": [NSDecimalNumber decimalNumberWithString:@"35820.00"]
};
NSDictionary *car3 = @{
    @"make": @"Volkswagen",
    @"model": @"Jetta A5",
    @"price": [NSDecimalNumber decimalNumberWithString:@"16675.00"]
};
NSDictionary *car4 = @{
    @"make": @"Volkswagen",
    @"model": @"Jetta A4",
    @"price": [NSDecimalNumber decimalNumberWithString:@"16675.00"]
};
NSMutableArray *cars = [NSMutableArray arrayWithObjects:
                        car1, car2, car3, car4, nil];

NSSortDescriptor *priceDescriptor = [NSSortDescriptor
                                     sortDescriptorWithKey:@"price"
                                                 ascending:YES
                                                  selector:@selector(compare:)];
NSSortDescriptor *modelDescriptor = [NSSortDescriptor
                                     sortDescriptorWithKey:@"model"
                                     ascending:YES
                                     selector:@selector(caseInsensitiveCompare:)];

NSArray *descriptors = @[priceDescriptor, modelDescriptor];
[cars sortUsingDescriptors:descriptors];
NSLog(@"%@", cars);    // car4, car3, car1, car2

The descriptor’s selector is called on each key’s value, so in the above code, we’re calling compare: on item[@"price"] and caseInsensitiveCompare: on item[@"model"] for each pair of items in the array.

过滤可变数组

可变数组的过滤方法和不可变数组的过滤方法一样,唯一的区别就是可变数组在过滤的时候不会生产新数组对象。

注意事项

As with all mutable collections, you’re not allowed to alter it in the middle of an enumeration. This is covered in the Enumeration Considerations section of the NSSet module, but instead of usingallObjects for the snapshot, you can create a temporary copy of the original array by passing it to the arrayWithArray: class method.

12-6 NSArray的更多相关文章

  1. OC语言基础之NSArray

    0.数组的分类 NSArray :不可变数组 NSMutableArray : 可变数组 1: // @[] 只创建不可变数组NSArray 2: /* 错误写法 3: NSMutableArray ...

  2. iOS---数据本地化

    本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

  3. Foundation框架

    1.框架是由许多类.方法.函数.文档按照一定的逻辑组织起来的集合,以便使研发程序变的更容易 清除缓存,删除这个文件夹下的所有文件/Users/fanyafang/Library/Developer/X ...

  4. iOS开发零碎知识点

    记录一些常用和不常用的iOS知识点,防止遗忘丢失.(来源为收集自己项目中用到的或者整理看到博客中的知识点),如有错误,欢迎大家批评指正:如有好的知识点,也欢迎大家联系我,添加上去.谢谢! 一.调用代码 ...

  5. Objective-C中Block语法、Block使用以及通过Block实现数组排序

    Block:语法块,本质上是匿名函数(没有名称的函数) 标准C里面没有Block,C语言的后期扩展版本,加入了匿名函数 在C++.JS.Swift等语言有类似语法,叫做闭包 Block语法和C语言里的 ...

  6. 【转】UITextView 修改键盘 的return按钮

    原文:http://www.apkbus.com/blog-107838-45740.html 1 #import <UIKit/UIKit.h>2 3 @interface TextVi ...

  7. iOS数据本地化

    本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

  8. ObjectiveC 深浅拷贝学习

    在ObjC中,什么是深浅拷贝? 深浅拷贝分别指深拷贝和浅拷贝,即mutableCopy和copy方法. copy复制一个不可变对象,而mutableCopy复制一个mutable可变对象. 什么时候用 ...

  9. iOS雷达图 iOS RadarChart实现

    实现效果 刚拿到设计稿的时候大概看了一眼,当时心里想着放张背景图,然后计算下相应点的坐标,在最上面画一层就OK了,其实一开始实现的时候也确实是这么做的,然后我就日了狗了,发现设计稿上多层五边形的间隔不 ...

  10. Xcode 7.0 SDK(Software Development Kit) 及 Sandbox(沙盒) 存放路径

    1. Sandbox(沙盒) 存放路径 我的硬盘/Users/wj121/Library/Developer/CoreSimulator/Devices/879D7E35-BE50-4620-97E1 ...

随机推荐

  1. [WC2005]双面棋盘

    description 洛谷 给出一个\(n\times n\)的黑白棋盘. \(m\)次操作,每次将一个格子进行颜色翻转,求每次操作后的黑白四连通块数. data range \[n\le 200, ...

  2. 一些技巧 && 常数优化 && 出现の错误

    开坑原因 7.21 今天DTZ大爷教了我一个算欧拉函数的好方法......是质因数复杂度的 这让我想到,这些小技巧小idea,很多时候,可能就是考场上最致命.最一击必杀的"大招" ...

  3. [NOIP2017]逛公园 最短路图 拓扑序DP

    ---题面--- 题解: 挺好的一道题. 首先我们将所有边反向,跑出n到每个点的最短路,然后f[i][j]表示从i号节点出发,路径长比最短路大j的方案数. 观察到,如果图中出现了0环,那么我们可以通过 ...

  4. HDU3480:Division——题解

    http://acm.hdu.edu.cn/showproblem.php?pid=3480 将一列数划分成几个集合,这些集合的并集为该数列,求每个数列的(最大值-最小值)^2的和的最小值. 简单的d ...

  5. POJ.1797 Heavy Transportation (Dijkstra变形)

    POJ.1797 Heavy Transportation (Dijkstra变形) 题意分析 给出n个点,m条边的城市网络,其中 x y d 代表由x到y(或由y到x)的公路所能承受的最大重量为d, ...

  6. async的基本用法

    1. async函数的基本形式 //函数声明 async function foo() {} //函数表达式 const foo = async function () {}; //对象的方法 let ...

  7. PowerDesigner 技巧【3】

    一.PowerDesigner导出所有SQL脚本: 一般的导出SQL脚本只需要下面两个步骤: 1.database->change current DBMS(选择需要导出的数据库类型): 2.d ...

  8. HDU 3277 最大流+二分

    Marriage Match III Time Limit: 10000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  9. java后台svg转成png

    1.替换img地址 /** * 替换img地址 * @param str -- 前台svg字符串 * @return */ private String transferImgPath(HttpSer ...

  10. 常见的Java问题

    1.什么是java虚拟机?为什么java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件. Java被 ...