【问题标题】:What is the most efficient way to test every number in a sequence against a sequence of ranges?根据范围序列测试序列中每个数字的最有效方法是什么?
【发布时间】:2020-04-11 21:39:45
【问题描述】:

我有两个数组。第一个序列是双打列表。第二个是范围列表。序列和数组的长度总是相同的。测试第一个数组中的每个元素是否在第二个数组中相同索引的范围内的最有效方法是什么?

有没有一种有效的方法来使用某种矩阵库来做到这一点?

我想要达到的目标的片段:

let A: [Double] = [1, 2, 3, 4, 5]
let B: [Range] = [0..2, 1..3, 2..4, 5..6, 7..8]

// TODO: Test each item in A against the range in B at the same index
// e.g. (0..2).contains(1) && (1..3).contains(2) && ... so on

如果所有项目都匹配,我想以 True 结束,否则以 false 结束。我需要循环执行这个测试,所以我想找到最有效的方法来做这个比较。

【问题讨论】:

  • 那么,您要确保 A 中的第一个双精度值在 B 的第一个范围内,第二个范围内的第二个双精度值,等等?
  • @HalR - 是的。没错
  • 可能有比此处使用矩阵库的答案更快的计算方法,但您需要重新组织数据以优化矩阵运算。这可能会使程序的其他部分更加复杂(或需要以不同格式复制信息)。 “最有效”在这里真的很重要,还是您的意思是“相当快”(下面的答案是)?使其绝对是最有效的还取决于出现问题的可能性。如果可能发生故障,矩阵的计算量往往会超出必要。
  • (这是您程序中如此重要的一部分,是否值得将非常快的单行操作转换为需要重新组织数据结构的复杂代码页面?)
  • 当然,带有一些 simd 的混合解决方案仍然非常有用,但它们不是解决这个问题的通用解决方案;它们将成为您问题的定制解决方案。在这些频率下,您确实需要考虑诸如内存局部性、内存缓存和复制之类的事情。在评估什么有帮助之前,您将需要一个完整的问题的良好、诚实的基准。 (当然,我的第一目标是重新设计以减少所需的频率,或者允许更多的部分搜索。只需做更少的工作总是一个巨大的胜利。)

标签: arrays swift


【解决方案1】:

我可能会这样做:

func all(_ values: [Double], in ranges: [Range<Double>]) -> Bool {
    zip(values, ranges).allSatisfy { $1 ~= $0 }
}

这样

let values: [Double] = [1,4,3]
let ranges: [Range<Double>] = [
    0..<3,
    1..<5,
    2..<6
]

let result = all(values, in: ranges)

不要混淆这个问题,但我可能会将其设为通用,因为没有理由将其限制为特定类型或特定类型的范围:

func all<T, U: RangeExpression>(_ values: [T], in ranges: [U]) -> Bool where U.Bound == T {
    zip(ranges, values).allSatisfy(~=)
}

正如 Jessy 指出的那样,如果您将其翻转为使用 zip(ranges, values),那么您可以使用 allSatisfy(~=)

【讨论】:

  • 您认为lazy 在这里重要吗?我认为allSatisfy 应该懒惰地迭代而不是急切地。
  • 确实,不需要lazy。已删除。
  • 翻转它! ?zip(ranges, values).allSatisfy(~=)
【解决方案2】:

你可以这样做:

let doubles: [Double] = [1.0, 2.0, 4.7, 2.5, 1.1]
let ranges: [ClosedRange<Double>] = [0...2, 1...2, 1...5, -1...3, 1...2]

let result = zip(doubles, ranges).allSatisfy { $1.contains($0) }

result 是一个布尔值,如果给定的双精度值在给定的范围内,它应该是 true,否则,它应该是 false。请记住,如果两个数组的计数不同,则结果将是 false

【讨论】:

    猜你喜欢
    • 2011-03-17
    • 2015-06-26
    • 1970-01-01
    • 2015-02-21
    • 2014-02-11
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    相关资源
    最近更新 更多