【问题标题】:Swift, How can I reverse specific elements in arrays?Swift,如何反转数组中的特定元素?
【发布时间】:2021-12-21 11:04:25
【问题描述】:

我有一个数组,里面有不同的元素,它看起来像这样:

Vehicles = [ Auto(brand: "bmw", color: "red"),
             Auto(brand: "mazda", color: "red"),
             Auto(brand: "alfa romeo", color: "red"),
             Bike(brand: "suzuki", color: "blue"),
             Bike(brand: "yamaha", color: "black") ]

在这种情况下,我需要根据“颜色”来反转它,所以数组会是这样的:

Vehicles = [ Auto(brand: "alfa romeo", color: "red"),
             Auto(brand: "mazda", color: "red"),
             Auto(brand: "bmw", color: "red"),
             Bike(brand: "suzuki", color: "blue"),
             Bike(brand: "yamaha", color: "black") ]

具有相同颜色的元素相互跟随,例如“子组”,我需要反转每个子组。即:[a,b,c,d,e,f,g,h,i],如果 a,b,c 为颜色 1,d,e,f 颜色为 2,g,h,i 为颜色 3,就像 [(a,b,c), (d,e,f), (g,h,i)],顺序应该是 [(c,b,a), (f, e, d), ( i,h,g)] 等 [c,b,a,f,e,d,i,h,g]

【问题讨论】:

  • 反向?你的意思是按颜色排序? Vehicles.sort { $0.color > $1.color }?
  • 如果 yamaha 也是蓝色的,你是不是也要反转 yamaha 和 suzuki?
  • @Sulthan Sort 我猜但我需要保持相同的顺序但颠倒,如果 x y z 车是红色的,则顺序应该是那些红色车的 z y x
  • @Sweeper 是的,在这种情况下也是如此
  • 因此您可能希望同时对它们进行排序?是按品牌升序还是按颜色降序? Vehicles.sort { $0.brand == $1.brand ? $0.color > $1.color : $0.brand < $1.brand }

标签: arrays swift


【解决方案1】:

您可以分三个步骤完成此操作:

  1. 根据颜色变化将您的收藏分为子收藏。 Apple 的swift-algorithms 包有一个名为chunked(by:) 的运算符非常适合此操作。 Read here 关于将包依赖项添加到您的应用程序。

  2. 反转每个子集合。您可以为此使用标准库reversed() 方法。

  3. 连接子集合。您可以为此使用标准库joined() 方法。

vehicles = vehicles
    .chunked { $0.color == $1.color }
    .map { $0.reversed() }
    .joined()

如果您想在 chunked 谓词中使用更复杂的逻辑,则需要使用命名参数,以便声明其返回类型:

vehicles = vehicles
    .chunked { a, b -> Bool in
        switch (a.type, b.type) {
        case (.car, .car): return a.color == b.color
        case (.bike, .bike): return a.color == b.color
        default: return false
        }
    }
    .map { $0.reversed() }
    .joined()

【讨论】:

  • 是否可以在分块函数中使用 switch case?因为车辆数组包含不同种类的数据
  • 我已经更新了我的答案。
  • chunked()闭包中,你有2个参数,它们是来自vehicles的2个对象。您可以按照您想要的方式比较它们,但如果您希望它们位于相同的 chunk 中,则返回 true,否则,返回 false。所以做任何你想要的比较,要么只是颜色、类型、其他属性等。
【解决方案2】:

使用模型和输入:

protocol Vehicle: CustomStringConvertible {
    var brand: String { get set }
    var color: String { get set }
}

extension Vehicle {
    var description: String {
        "Brand: \(brand) - color: \(color)"
    }
}
struct Bike: Vehicle {
    var brand: String
    var color: String
}
struct Auto: Vehicle {
    var brand: String
    var color: String
}

let vehicles: [Vehicle] = [ Auto(brand: "bmw", color: "red"),
                            Auto(brand: "mazda", color: "red"),
                            Auto(brand: "alfa romeo", color: "red"),
                            Bike(brand: "suzuki", color: "blue"),
                            Bike(brand: "suzuki2", color: "blue"),
                            Bike(brand: "suzuki3", color: "blue"),
                            Bike(brand: "yamaha", color: "black"),
                            Bike(brand: "yamaha2", color: "black")]

一个可能的解决方案,不需要 Apple 的额外 Collection Packages 作为mentionned by rob mayoff

// Here we create batches, ie subgroups of Vehicle with the same color using `reduce(into:_)`

let batched = vehicles.reduce(into: [[Vehicle]]()) { partialResult, aVehicle in
    //If there is already a batch, we check the last one, and inside that batch, we check the last Vehicle color
   // If it's the same color of the one currently checked (aVehicle), then we append it
    if var lastBatch = partialResult.last, let lastVehicle = lastBatch.last, lastVehicle.color == aVehicle.color {
        lastBatch.append(aVehicle)
        partialResult[partialResult.count - 1] = lastBatch
    } else {
        partialResult.append([aVehicle]) //We create a new batch
    }
}

print("batched: \(batched)")

// Here we reverse each batch
let reversedBatch = batched.map { aBatch -> [Vehicle] in
    return aBatch.reversed() //return can be omitted here
}
print("reversedBatch: \(reversedBatch)")

//We remove the subgroup, flattening the array
let reversed = reversedBatch.flatMap { $0 }
print("reversed: \(reversed)")

现在,我们有了主要的想法,我们可以一次完成第一个操作和第二个操作。我们不是追加,而是把它作为批处理的开始

let batchedAndReversed = vehicles.reduce(into: [[Vehicle]]()) { partialResult, aVehicle in
    if var lastBatch = partialResult.last, let lastVehicle = lastBatch.last, lastVehicle.color == aVehicle.color {
        lastBatch.insert(aVehicle, at: 0)
        partialResult[partialResult.count - 1] = lastBatch
    } else {
        partialResult.append([aVehicle]) //We create a new batch
    }
}
let reversed2 = batchedAndReversed.flatMap { $0 }
print("reversed2: \(reversed2)")

【讨论】:

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