【问题标题】:Pick closest NSNumber from array从数组中选择最近的 NSNumber
【发布时间】:2012-12-29 23:16:47
【问题描述】:

我有一个包含一堆NSNumbers 的数组。当用户停止拖动它时,我从UISlider 得到一个特定的值。我想从数组中获取关闭数。

例如,如果用户将UISlider 拖到13,并且NSArray 包含NSNumbers1015;我想从数组中获取15

数组示例:

NSArray *values = [NSArray arrayWithObjects:[NSNumber numberWithInt:15],
                    [NSNumber numberWithInt:20],
                    [NSNumber numberWithInt:30],
                    [NSNumber numberWithInt:45],
                    [NSNumber numberWithInt:60],
                    [NSNumber numberWithInt:90],
                    [NSNumber numberWithInt:110], nil];

如何从数组中得到正确的数字?

【问题讨论】:

  • 我不明白这个问题。为什么不计算数组中每个元素的值的差异,并使用绝对值来决定哪个最接近?
  • 当然可以。但是如果我有一个包含 1000 个值的数组呢?那是相当多的计算和内存使用。
  • 数组迭代在 Objective-C 中非常有效。我经常使用它而没有性能问题。尝试使用 1000 个值并确定它是否足够快。解决方案必须足够好。
  • 我不同意。该声明仅取决于项目的要求。一般来说,我认为“足够好”不是解决方案,除非它不可持续。因此,如果由于某种原因,6 个月内的数组将是 100.000,它可能是不可持续的。
  • 您正在考虑一个具有 100.000 个不同离散值的滑块?听起来很奇怪。

标签: objective-c nsarray nsnumber


【解决方案1】:

在您的帖子中,数组已排序。如果它总是排序,你可以使用二分搜索。 NSArray 有一个方便的方法:

CGFloat targetNumber = mySlider.value;
NSUInteger index = [values indexOfObject:@(targetNumber)
    inSortedRange:NSMakeRange(0, values.count)
    options:NSBinarySearchingFirstEqual | NSBinarySearchingInsertionIndex
    usingComparator:^(id a, id b) {
        return [a compare:b];
    }];

现在有四种可能:

  1. values 的每个元素都大于targetNumberindex 为零。
  2. values 的每个元素都小于targetNumberindex 等于values.count
  3. values 包含targetNumberindextargetNumbervalues 中的索引。
  4. indexvalues 中大于targetNumber 的最小元素的索引。

我已经按照我们处理它们的顺序巧妙地列出了这些案例。这是案例1:

if (index == 0) {
    return [values[0] floatValue];
}

这里是案例 2:

if (index == values.count) {
    return [[values lastObject] floatValue];
}

我们可以一起处理案例 3 和案例 4:

CGFloat leftDifference = targetNumber - [values[index - 1] floatValue];
CGFloat rightDifference = [values[index] floatValue] - targetNumber;
if (leftDifference < rightDifference) {
    --index;
}
return [values[index] floatValue];

【讨论】:

  • 就像一个魅力,除了它应该是[values[0] floatValue]。也似乎是可持续的。
【解决方案2】:

如果您的 values 数组是有序的,并且您总是希望该值大于(或等于)输入的值,您可以执行以下操作:

NSInteger count = 0;
do {
    count++;
} while (enteredNum > [values[count] intValue]);

// Do something with [values[count] intValue]

【讨论】:

  • 好的,但是;这意味着如果我得到 11,我会得到 15,而不是 10……这不是最接近的数字,因此很遗憾不是我的问题的答案。
  • 所以记录前一个和较大的,然后将它们相互比较。
  • 如果enteredNum 大于最大值,这将崩溃,因此可能仅适用于具有滑块约束的特殊情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-18
  • 2019-01-06
  • 1970-01-01
  • 2016-01-18
  • 2021-09-04
  • 2016-06-08
  • 1970-01-01
相关资源
最近更新 更多