我在SWIFT中有一个数组
let a = [0.0, 0.00250, 0.0050, 0.00749, 0.01, 0.01251, 0.01499, 0.0175, 0.02, 0.022, 0.025] // is always a sequence (increasing)
我还有第二个数组
let b = [0.0, 0.004, 0.008, 0.012, 0.016, 0.02, 0.024, 0.028, 0.032, 0.036, 0.04, 0.044, 0.048, 0.052, 0.056] // is always a sequence (increasing)
我必须找到“b”的所有元素,即> = a [0]& < = a [a.count-1]并用这些值填充向量“c”。
那样
let c = [0.0, 0.004, 0.008, 0.012, 0.016, 0.02, 0.024] // ANSWER
最有效的方法是什么?
答案 0 :(得分:1)
由于您知道两个序列都在增加,因此您只需要使用数组a
的第一个和最后一个元素。使用这些方法,您可以使用index(where:)
方法在b
数组中查找相应的索引,从而完成谓词>= (first of a)
和<= (last of a)
。 E.g。
if let aFirst = a.first, let aLast = a.last,
let startIndex = b.index(where: { $0 >= aFirst }),
case let endIndex = b.index(where: { $0 > aLast }) ?? a.endIndex {
let c = b[startIndex..<endIndex] // note: this is an ArraySlice<Double>
// wrap in Array(..) to construct a new array
print(c)
// [0.0, 0.0040000000000000001, 0.0080000000000000002, 0.012, 0.016, 0.02, 0.024]
}
或者,正如@MartinR所提议的那样,我们可以猜测,如果我们从index(where:)
的末尾开始,我们将会更快地完成第二次b
调用的谓词。检查满足$0 <= aLast
条件的第一个元素:
if let aFirst = a.first, let aLast = a.last,
let startIndex = b.index(where: { $0 >= aFirst }),
case let endIndex = b.reversed().index(where: { $0 <= aLast })!.base {
/* ^^^^^- as proposed by @MartinR */
let c = b[startIndex..<endIndex]
print(c)
// [0.0, 0.0040000000000000001, 0.0080000000000000002, 0.012, 0.016, 0.02, 0.024]
}
最后,此方法(以及当前可用的其他答案中的filter
方法)在O(n)
中运行。一种更高效的方法是使用二进制搜索,它在O(log n)
渐近运行。正如@MartinR所提到的,一个很好的起点可能是Rosetta代码中的二进制搜索Swift实现:
如本Q&amp; A中所述:
回答评论:
......我还有另外一个我忘记提及的问题。我还有一个 数组
y
与b
具有完全相同的元素数。我们可以 将这些视为信号的X
和Y
值。我必须选择 我在y
中选择的元素匹配来自b
的元素。
最简单的解决方案只是应用计算出的startIndex
和endIndex
来切出y
数组的一部分(就像你将b
的一部分切成一样构建c
)。
let d = y[startIndex..<endIndex]
// assumes y.count == b.count, and that these are not slices
// with non-matching indices
但是,我认为更好的方法是使用zip
。只需压缩y
和b
并使用结果构建一个元组数组,然后您可以将上面的谓词应用于压缩序列的b
成员:
let y = Array(1...b.count)
if let aFirst = a.first, let aLast = a.last,
let startIndex = bAndY.index(where: { $0.0 >= aFirst }),
case let endIndex = bAndY.index(where: { $0.0 > aLast }) ?? a.endIndex {
let cAndD = bAndY[startIndex..<endIndex]
print(cAndD)
/* [(0.0040000000000000001, 2),
(0.0080000000000000002, 3),
(0.012, 4),
(0.016, 5),
(0.02, 6),
(0.024, 7)] */
}
自然地构造cAndD
数组会产生一些小的开销,但除非你编写一些真正的HPC应用程序,否则你不必担心这一点。
答案 1 :(得分:0)
您可以在阵列上使用filter
函数,它将返回一个新数组。您可以比较值是&gt; = a [0]还是&lt; = a [a.count-1]。显然,您应该始终检查数组是否包含多于0个元素。
let smallestValue = a[0]
let highestValue = a[a.count-1]
let c = b.filter() { return smallestValue <= $0 && $0 <= highestValue }
计算索引
因为b总是增加固定量,例如0.004在你的情况下,你可以计算你的指数。这非常有效,因为您只进行了两次比较,最多两次计算非常快。
let smallestValueA = a[0]
let highestValueA = a[a.count-1]
let smallestValueB = b[0]
let highestValueB = b[b.count-1]
let increase = 0.004 //based on your example
var smallestIndex: Int = 0
var highestIndex: Int = b.count
if smallestValueA > smallestValueB {
smallestIndex = Int((smallestValueA - smallestValueB) / increase).rounded(.up)
}
if highestValueA < highestValueB {
highestIndex = Int(((highestValueB - highestValueA) - smallestValueB) / increase)
}
let c = b[smallestIndex..<highestIndex] //[0.0, 0.0040000000000000001, 0.0080000000000000002, 0.012, 0.016, 0.02, 0.024]
答案 2 :(得分:0)
另一种方法是:
let c = b.filter() { return (a.first)! <= $0 && $0 <= (a.last)! }
答案 3 :(得分:-1)
您不应将值保存为数组。
如果彼此不相等,
保存一组并使用
let c = a.intersection(b)