码迷,mamicode.com
首页 > 其他好文 > 详细

12-6 NSArray

时间:2015-11-27 12:59:22      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

原文: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(@"First german make: %@", germanMakes[0]);
NSLog(@"First U.K. make: %@", [ukMakes objectAtIndex:0]);

正如你所见,不同的数据可以使用中括号加上下标的方式取得或者使用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
for (int i=0; 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 ValueDescription
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(4, 2)];
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:@"BMW F25" atIndex:0];
// Remove BMW F25 from front
[brokenCars removeObjectAtIndex:0];
// Remove Audi Quattro
[brokenCars removeObject:@"Audi Quattro"];

 

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

// Change second item to Audi Q5
[brokenCars replaceObjectAtIndex:1 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

标签:

原文地址:http://www.cnblogs.com/ios123/p/4976700.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!