Arrays 排序数组和查找更改-Swift
好的,我有一个流,它不断地以很快的速度接收一个数组。这是我想做的 如果数组相同,则不要执行任何操作。如果不同,则创建一个新数组,除已更改的值外,其他值均为nil 例如: 传入数组1:[1,1,1,1] 传入数组2:[1,1,2,1] 我想创建:[nil,nil,2,nil]。仅标记更改 我做了一些有用的东西,我只是觉得没有效率。这是最好的方法吗Arrays 排序数组和查找更改-Swift,arrays,sorting,swift,optimization,Arrays,Sorting,Swift,Optimization,好的,我有一个流,它不断地以很快的速度接收一个数组。这是我想做的 如果数组相同,则不要执行任何操作。如果不同,则创建一个新数组,除已更改的值外,其他值均为nil 例如: 传入数组1:[1,1,1,1] 传入数组2:[1,1,2,1] 我想创建:[nil,nil,2,nil]。仅标记更改 我做了一些有用的东西,我只是觉得没有效率。这是最好的方法吗 var storedArray = [Int](count: 10, repeatedValue: 0) //array for comparing
var storedArray = [Int](count: 10, repeatedValue: 0) //array for comparing
func incomingArray(data: [Int]) {
if data == storedArray {return} //do nothing if its the same
var tempArray = [Int?](count: 10, repeatedValue: nil) //nil array
for index in 0...9 {
if storedArray[index] != data[index] {
tempArray[index] = data[index] //replace the temp array index
}
}
//send the completed tempArray to do work ....
storedArray = incomingArray //save the stored as the current data
}
所以上面的代码是有效的。只是效率不高。有更好的主意吗
谢谢
更新1:
我在原来的帖子里搞错了。而不是Int。它们是UInt8 以下是一些加快代码速度的方法: 1) 不要使用
Int?
数组,而是使用普通的Int
数组,不要将元素标记为nil
,而是将它们标记为某种特殊的整数值。我不知道那个值是什么,可能0是好的,或者-1,或者Int.max
更新:上述更改使我的性能提高了约10%
2) 回收结果数组。以便您可以跳过以下代码:
var tempArray = [Int?](count: 10, repeatedValue: nil)
或者更好,让调用者通过inout
参数传入,这样您就不必担心它的所有权
更新:上述更改使我的性能提高了约50%
以下是此问题中建议的所有版本的代码:
import UIKit
import XCTest
var storedArray1 = [Int?](count: 10, repeatedValue: 0) //array for comparing
func processIncomingArray1(data: [Int]) {
var tempArray = [Int?](count: 10, repeatedValue: nil) //nil array
for index in 0...9 {
if storedArray1[index] != data[index] {
tempArray[index] = data[index] //replace the temp array index
}
}
storedArray1 = tempArray
}
var storedArray2 = [Int](count: 10, repeatedValue: 0)
func processIncomingArray2(data: [Int]) {
var tempArray = [Int](count: 10, repeatedValue: Int.max)
for index in 0...9 {
if storedArray2[index] != data[index] {
tempArray[index] = data[index]
}
}
storedArray2 = tempArray
}
var storedArray3 = [Int](count: 10, repeatedValue: Int.max)
func processIncomingArray3(data: [Int], inout result: [Int]) {
for index in 0...9 {
if result[index] != data[index] {
result[index] = data[index]
}
}
}
// Given two sequences, return a sequence of 2-tuples (pairs)
public func zip<A: SequenceType, B: SequenceType>(a: A, b: B)
-> ZipSequence<A, B>
{
return ZipSequence(a, b)
}
// Lazy sequence of tuples created from values from two other sequences
public struct ZipSequence<A: SequenceType, B: SequenceType>: SequenceType {
private var a: A
private var b: B
public init (_ a: A, _ b: B) {
self.a = a
self.b = b
}
public func generate() -> ZipGenerator<A.Generator, B.Generator> {
return ZipGenerator(a.generate(), b.generate())
}
}
// Generator that creates tuples of values from two other generators
public struct ZipGenerator<A: GeneratorType, B: GeneratorType>: GeneratorType {
private var a: A
private var b: B
public init(_ a: A, _ b: B) {
self.a = a
self.b = b
}
mutating public func next() -> (A.Element, B.Element)? {
switch (a.next(), b.next()) {
case let (.Some(aValue), .Some(bValue)):
return (aValue, bValue)
default:
return nil
}
}
}
func differences<T: Equatable>(lhs: [T], rhs: [T]) -> [Int] {
// indexedPairs is a sequence of (index, (left-hand val, right-hand val))
let indexedPairs = enumerate(zip(lhs,rhs))
// the lazy may or may not help here, benchmark to find out...
return lazy(indexedPairs).filter { (index, pair) in
// only return different pairs
pair.0 != pair.1
}.map {
// only return the index not the values
$0.0
}.array
}
var storedArray4 = [Int](count: 10, repeatedValue: Int.max)
func processIncomingArray4(data: [Int]) {
let diffs = differences(storedArray4, data)
if !diffs.isEmpty {
// send new data and diff indices for further processing
// then overwrite the old array
storedArray4 = data
}
}
func differences5<T: Equatable>(lhs: [T], rhs: [T]) -> [Int] {
var diffs: [Int] = []
// still using zip, since this guards against the two
// arrays being of different sizes - doesn’t seem to
// impact performance
for (i,(l,r)) in zip(indices(lhs),zip(lhs,rhs)) {
if l != r { diffs.append(i) }
}
return diffs
}
var storedArray5 = [Int](count: 10, repeatedValue: Int.max)
func processIncomingArray5(data: [Int]) {
let diffs = differences5(storedArray4, data)
if !diffs.isEmpty {
// send new data and diff indices for further processing
// then overwrite the old array
storedArray5 = data
}
}
class StackOverflowTests: XCTestCase {
func testPerformanceExample1() {
var data = [1,2,3,4,5,6,7,8,9,10]
self.measureBlock() {
for i in 1...100000 {
processIncomingArray1(data)
}
}
}
func testPerformanceExample2() {
var data = [1,2,3,4,5,6,7,8,9,10]
self.measureBlock() {
for i in 1...100000 {
processIncomingArray2(data)
}
}
}
func testPerformanceExample3() {
var data = [1,2,3,4,5,6,7,8,9,10]
self.measureBlock() {
for i in 1...100000 {
processIncomingArray3(data, &storedArray3)
}
}
}
func testPerformanceExample4() {
var data = [1,2,3,4,5,6,7,8,9,10]
self.measureBlock() {
for i in 1...100000 {
processIncomingArray4(data)
}
}
}
func testPerformanceExample5() {
var data = [1,2,3,4,5,6,7,8,9,10]
self.measureBlock() {
for i in 1...100000 {
processIncomingArray5(data)
}
}
}
}
导入UIKit
导入测试
var storedArray1=[Int?](计数:10,重复值:0)//用于比较的数组
func processIncomingArray1(数据:[Int]){
var tempArray=[Int?](计数:10,repeatedValue:nil)//nil数组
对于0…9中的索引{
如果storedArray1[index]!=数据[index]{
tempArray[index]=data[index]//替换临时数组索引
}
}
storedArray1=tempArray
}
var storedArray2=[Int](计数:10,重复值:0)
func processIncomingArray2(数据:[Int]){
var tempArray=[Int](计数:10,repeatedValue:Int.max)
对于0…9中的索引{
如果storedArray2[index]!=数据[index]{
tempArray[索引]=数据[索引]
}
}
storedArray2=tempArray
}
var storedArray3=[Int](计数:10,重复值:Int.max)
func processIncomingArray3(数据:[Int],输入输出结果:[Int]){
对于0…9中的索引{
如果结果[索引]!=数据[索引]{
结果[索引]=数据[索引]
}
}
}
//给定两个序列,返回一个2元组(对)序列
公共职能邮政编码(a:a,b:b)
->拉链序列
{
返回ZipSequence(a、b)
}
//从另外两个序列的值创建的元组的惰性序列
公共结构ZipSequence:SequenceType{
私有变量a:a
私有变量b:b
公共初始化(a:a,b:b){
self.a=a
self.b=b
}
public func generate()->ZipGenerator{
返回ZipGenerator(a.generate(),b.generate())
}
}
//从其他两个生成器创建值元组的生成器
公共结构ZipGenerator:GeneratorType{
私有变量a:a
私有变量b:b
公共初始化(a:a,b:b){
self.a=a
self.b=b
}
修改公共函数next()->(A.Element,B.Element){
开关(a.next(),b.next()){
小格(.Some(aValue),.Some(bValue)):
返回值(aValue,bValue)
违约:
归零
}
}
}
函数差异(左[T],右[T])->[Int]{
//indexedPairs是(索引,(左侧val,右侧val))的序列
让indexedPairs=枚举(zip(左、右))
//懒惰的人可能会也可能不会帮上忙,看看吧。。。
返回lazy(indexedPairs)。在
//只返回不同的对
对.0!=对.1
}.地图{
//只返回索引,不返回值
$0.0
}.数组
}
var storedArray4=[Int](计数:10,重复值:Int.max)
func processIncomingArray4(数据:[Int]){
设差异=差异(storedArray4,数据)
如果!差异是空的{
//发送新数据和差异索引以进行进一步处理
//然后覆盖旧数组
storedArray4=数据
}
}
函数差分5(左[T],右[T])->[Int]{
变量差异:[Int]=[]
//仍然使用zip,因为这可以防止两个
//不同大小的数组-看起来不一样
//冲击性能
对于zip中的(i,(l,r))(索引(lhs),zip(lhs,rhs)){
如果l!=r{diff.append(i)}
}
回差
}
var storedArray5=[Int](计数:10,重复值:Int.max)
func processIncomingArray5(数据:[Int]){
设差异=差异5(storedArray4,数据)
如果!差异是空的{
//发送新数据和差异索引以进行进一步处理
//然后覆盖旧数组
storedArray5=数据
}
}
类StackOverflowTests:XCTestCase{
func testPerformanceExample1(){
var数据=[1,2,3,4,5,6,7,8,9,10]
self.measureBlock(){
因为我有10万美元{
processIncomingArray1(数据)
}
}
}
func testPerformanceExample2(){
var数据=[1,2,3,4,5,6,7,8,9,10]
self.measureBlock(){
因为我有10万美元{
processIncomingArray2(数据)
}
}
}
func测试性能示例3(){
var数据=[1,2,3,4,5,6,7,8,9,10]
self.measureBlock(){
因为我有10万美元{
processIncomingArray3(数据和存储阵列3)
}
}
}
func testPerformanceExample4(){
var数据=[1,2,3,4,5,6,7,8,9,10]
self.measureBlock(){
因为我有10万美元{
processIncomingArray4(数据)
}
}
}
func测试性能示例5(){
var数据=[1,2,3,4,5,6,7,8,9,10]
self.measureBlock(){
因为我有10万美元{
processIncomingArray5(数据)
}
if data == storedArray {return}
func differences<T: Equatable>(lhs: [T], rhs: [T]) -> [Int] {
// indexedPairs is a sequence of (index, (left-hand val, right-hand val))
let indexedPairs = enumerate(zip(lhs,rhs))
// the lazy may or may not help here, benchmark to find out...
return lazy(indexedPairs).filter { (index, pair) in
// only return different pairs
pair.0 != pair.1
}.map {
// only return the index not the values
$0.0
}.array
}
func incomingArray(data: [Int]) {
let diffs = differences(storedArray, data)
if !diffs.isEmpty {
// send new data and diff indices for further processing
// then overwrite the old array
storedArray = data
}
}
func differences<T: Equatable>(lhs: [T], rhs: [T]) -> [Int] {
var diffs: [Int] = []
// still using zip, since this guards against the two
// arrays being of different sizes - doesn’t seem to
// impact performance
for (i,(l,r)) in zip(indices(lhs),zip(lhs,rhs)) {
if l != r { diffs.append(i) }
}
return diffs
}