没有什么可以与 Python 的良好语法相匹配,但你可以这样做:
NSUInteger count = [myArray count];
NSArray * slice = [myArray subarrayWithRange:(NSRange){count-n, n}];
您还可以为以下内容编写一个类别NSArray
, 就像是:
@interface NSArray (jrdioko_slice)
- (NSArray *) jrdioko_sliceFrom:(NSInteger)start to:(NSInteger)stop;
@end
如果你想走这条路,Python源码肯定会值得学习。 A列表对象 http://svn.python.org/view/%2acheckout%2a/python/tags/r265/Objects/listobject.c?content-type=text%2Fplain创建一个切片对象 http://svn.python.org/view/%2acheckout%2a/python/tags/r265/Objects/sliceobject.c?content-type=text%2Fplain当执行切片操作时。切片对象的相关方法是PySlice_GetIndicesEx
。你只需要小心地将这些索引变成NSRange
。正如该函数中的评论所警告的那样“这比您想象的更难做到正确”。 (稍后我会尝试解决这个问题。)
更新:这里我们有一个切片类别NSArray
。索引计算逻辑几乎直接来自我上面链接的 Python 代码。*如果您不必担心 Python 切片的步幅部分,它实际上比我一开始想象的要容易得多。我已经通过一些测试运行了它,它的工作原理似乎与 Python 版本相同。
@interface NSArray (WSS_Slice)
- (NSArray *)WSS_arrayBySlicingFrom:(NSInteger)start to:(NSInteger)stop;
@end
// Python allows skipping any of the indexes of a slice and supplies default
// values. Skipping an argument to a method is not possible, so (ab)use
// NSNotFound as "not specified" index value. The other way to do this would
// be with varargs, which might be even handier if one decided to implement
// the stride functionality.
enum {
WSS_SliceNoIndex = NSNotFound
};
@implementation NSArray (WSS_Slice)
- (NSArray *)WSS_arrayBySlicingFrom:(NSInteger)start to:(NSInteger)stop {
// There's an important caveat here: specifying the parameters as
// NSInteger allows negative indexes, but limits the method's
// (theoretical) use: the maximum size of an NSArray is NSUIntegerMax,
// which is quite a bit larger than NSIntegerMax.
NSUInteger count = [self count];
// Due to this caveat, bail if the array is too big.
if( count >= NSIntegerMax ) return nil;
// Define default start and stop
NSInteger defaultStart = 0;
NSInteger defaultStop = count;
// Set start to default if not specified
if( start == WSS_SliceNoIndex ){
start = defaultStart;
}
else {
// If start is negative, change it to the correct positive index.
if( start < 0 ) start += count;
// Correct for out-of-bounds index:
// If it's _still_ negative, set it to 0
if( start < 0 ) start = 0;
// If it's past the end, set it to just include the last item
if( start > count ) start = count;
}
// Perform all the same calculations on stop
if( stop == WSS_SliceNoIndex ){
stop = defaultStop;
}
else {
if( stop < 0 ) stop += count;
if( stop < 0 ) stop = 0;
if( stop > count ) stop = count;
}
// Calculate slice length with corrected indexes
NSInteger sliceLength = stop - start;
// If no slice, return a new empty array
if( sliceLength <= 0 ){
return [NSArray array];
}
else {
return [self subarrayWithRange:(NSRange){start, sliceLength}];
}
}
@end
*Therefore I think I need to include a link to the Python License http://docs.python.org/release/2.6.5/license and also note that this may still be “Copyright © 2001-2010 Python Software Foundation; All Rights Reserved”, because although this looks to me like a separately-copyrightable derivative work, I ain't a lawyer.