【问题标题】:How can i filter and create ranges from NSIndexSet?如何从 NSIndexSet 过滤和创建范围?
【发布时间】:2018-11-13 20:45:14
【问题描述】:

我有一个由

创建的 NSIndexSet
NSIndexSet* groups = [self.specifiers indexesOfObjectsPassingTest:^(PSSpecifier*specifier, NSUInteger idx, BOOL *stop) {
return [(NSString*)[specifier.properties objectForKey:@"cell"] isEqualToString:@"KBGroupCell"]; }];

可能看起来像这样:

(0 3 5 8-9 12 14 17-19) 和给定的最大值为 25。

我希望过滤和创建范围,这样我就可以实现如下输出:

0-2
3-4
5-7
8-11
12-13
14-16
17-25

使用的数组是由用户而不是我自己填充的。 KBGroupCells 用于填充表中的页眉和页脚,因此不应连续识别。当我稍后填充我的表格时,我需要记住被忽略的数字(9、18 和 19)。

通过使用rangeAtIndex,我可以识别集合中包含多个的范围,因此可以用于查找要忽略的数字。

我怎样才能做到这一点?

【问题讨论】:

  • 1. 5-7 呢? 2. 请出示您的代码以填充此NSIndexSet。
  • 假设索引集包含0 3 8-9 10 15。结果应该是0-2, 3-7, 8-14, 15-25 还是0-2, 3-7, 8-9, 10-14, 15-25?
  • @rmaddy - NSIndexSet 不是一组索引和范围符号只是描述它的一种方式吗?所以0 3 8-9 10 15 实际上是0 3 8-10 15,因此您的问题没有实际意义?我认为 OP 希望创建从集合中存在的一系列索引的第一个索引开始的范围,这样的运行可能具有长度 1,并以不在集合中的下一个索引结束,该索引立即位于(或立即在集合结束之前)。
  • @rmaddy 你说的很对。不确定 5-7 发生了什么已将其重新编辑。对此感到抱歉!
  • @rmaddy 在该示例中,它将是 0-2、3-7、8-9、10-14、15-25。注意 9 将被忽略

标签: ios objective-c


【解决方案1】:

我假设你有 NSIndexSet:

    let original =   IndexSet(arrayLiteral: 0, 3, 5).union(IndexSet(integersIn: 8...9)).union( IndexSet.init(arrayLiteral: 12,14)).union(IndexSet(integersIn: 17...19)).union(IndexSet.init(arrayLiteral: 26,27))
    let nsIndex = original as! NSIndexSet

转换成IndexSet后就可以轻松得到两个数组了。一个是[NSRange],另一个是[closeRange]

    let index = nsIndex as! IndexSet
    let rangeView = index.rangeView
    print  ( Array(rangeView.enumerated().map{
      NSRange.init(location:($0.element.first!) , length: ((rangeView[$0.offset + 1].first!  - ($0.element.first!))))
    }.dropLast()))

    print  ( Array(rangeView.enumerated().map{
                ($0.element.first!)...(rangeView[$0.offset + 1].first!) - 1
        }.dropLast()))

如果是客观-C。就像这样:

NSMutableIndexSet * nsIndex =    [[NSMutableIndexSet alloc] init];
[nsIndex addIndex: 0];
[nsIndex addIndex: 3];
[nsIndex addIndex: 5];
[nsIndex addIndexesInRange:NSMakeRange(8, 2)];
[nsIndex addIndex: 12];
[nsIndex addIndex: 14];
[nsIndex addIndexesInRange:NSMakeRange(17, 3)];
[nsIndex addIndex: 26];
__block int count = 0;
__block NSMutableArray * ranges = [NSMutableArray array];
[nsIndex enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
    count ++;
    [ranges addObject:[NSValue valueWithRange: range]];
}];
NSMutableArray * result  = [NSMutableArray array];
for (NSUInteger location = 0 ; location < count - 1 ; location++) {
    NSUInteger loc = ((NSValue *) ranges[location]).rangeValue.location;
    [result addObject:[NSValue valueWithRange: (NSMakeRange( loc,  ((NSValue *) ranges[location + 1]).rangeValue.location -  loc))]];
}
NSLog(result.description);

或一轮:

__block NSUInteger temp = nsIndex.firstIndex;
__block NSMutableArray * result = [NSMutableArray array];
[nsIndex enumerateRangesWithOptions:NSEnumerationReverse usingBlock:^(NSRange range, BOOL * _Nonnull stop) {
    [result insertObject: [NSValue valueWithRange: NSMakeRange(range.location, temp - range.location)] atIndex:0];
    temp = range.location ;
}];
  result =  [result subarrayWithRange:NSMakeRange(0, result.count - 1)];
  NSLog(result.description);

【讨论】:

  • 你能告诉我这如何忽略我不想要的值吗?我还想将被忽略的索引添加到一个单独的数组中,但我很难理解究竟发生在哪里。
  • 如果block中任意range的长度> 1,收集NSMakeRange(range.location +1, range.length-1)
【解决方案2】:

这是一个可能的算法,编码和一些错误检查留作练习!

cursor <- theSet first contained index
result <- empty array

while cursor <= maxIndex
   start <- cursor
   while cursor <= maxIndex and theSet contains cursor do increment cursor
   while cursor <= maxIndex and theSet does not contain cursor do increment cursor
   newRange <- start to cursor-1
   add newRange to result
end

return result

该算法仅使用NSIndexSet 的两种方法 - 一种查找集合中的第一个索引,另一种测试索引是否在集合中。有一些“更高级别”的方法可能会加快算法的速度,但在 0-25 范围内逐步遍历索引就足够了。

HTH

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多