从阵列末尾切片NSArray [英] Slice NSArray from end of array

查看:147
本文介绍了从阵列末尾切片NSArray的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从数组的末尾(而不是开头)切片 NSArray 的最佳方法是什么(例如,找到包含最后几个的子数组)长度未知的 NSArray 的元素?在Python中,您可以使用负数索引来实现此目的,例如:

What is the best way to "slice" an NSArray from the end, rather than the beginning, of the array (for example, finding the subarray containing the last few elements of a NSArray of unknown length)? In Python, you can use negative indices to accomplish this, e.g.:

new_list = old_list[-5:-3]

Objective-C中最自然的方式是什么?

What's the most natural way to do this in Objective-C?

推荐答案

没有什么可以匹配Python的漂亮语法,但你可以这样做:

There's nothing to match Python's nice syntax for this, but you could do:

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源肯定会回报研究。 列表对象创建一个切片对象执行切片操作时。切片对象上的相关方法是 PySlice_GetIndicesEx 。您只需要小心将这些索引转换为 NSRange 。正如该功能中的评论所警告的那样这比你想象的更难做到。 (我稍后会试着解决这个问题。)

If you want to go this route, the Python source will certainly repay study. A list object creates a slice object when a slice operation is performed. The relevant method on a slice object is PySlice_GetIndicesEx. You'll just have to be careful turning those indexes into an NSRange. As the comment in that function warns "this is harder to get right than you might think". (I'll try to take a crack at this later.)

更新:这里我们在 NSArray上有一个切片类别。索引计算逻辑与我上面链接的Python代码非常相似。*如果你不必担心Python切片的步幅部分,它实际上比我想象的要容易得多。我通过一些测试运行它,它似乎与Python版本一样。

UPDATE: Here we have a slice category on NSArray. The index calculation logic is pretty much straight out of the Python code that I linked to above.* It's actually a lot easier than I thought at first if you don't have to worry about the stride part of a Python slice. I've run this through a few tests and it seems to work the same as the Python version.

@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

< sub> *因此我想我需要包含一个指向 Python许可证的链接,并注意到这个可能仍然是版权所有©2001-2010 Python软件基金会;保留所有权利,因为虽然这看起来像是一个单独版权的衍生作品,但我不是律师。

*Therefore I think I need to include a link to the Python 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.

这篇关于从阵列末尾切片NSArray的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆