首页 > 解决方案 > 根据(1)不完整的数组 B 和(2)按字母顺序对 Swift 中的数组 A 进行排序

问题描述

我有一个数组tags,其中包含几个带有id和的元素name。我还有一个数组order,其中存在一些元素tags。这是我想要实现的目标:

  1. 中的所有元素都tags应该按照order.
  2. 那些不存在order的元素应该在存在的元素之后按字母顺序排列order

我已经使用for循环解决了它(代码在 Playground 中运行):

import Foundation
import UIKit

struct Tag: Identifiable {
    var id: Int
    var name: String
}

// Ccc > Bbb > Aaa > Ddd > Eee
var tags = [Tag(id: 1000, name: "Ccc"), Tag(id: 1001, name: "Bbb"), Tag(id: 1002, name: "Aaa"), Tag(id: 1003, name: "Ddd"), Tag(id: 1004, name: "Eee")]

// Eee > Ddd > Ccc > Bbb > Aaa
tags.sort(by: { $0.name < $1.name })

// Bbb > Ddd
var idOrdering = [1001, 1003]

// Bbb > Ddd > Aaa > Ccc > Eee
for orderIndex in idOrdering.indices {
    // Get tag id.
    let tagId = idOrdering[orderIndex]

    let tagIndex = tags.firstIndex(where: { $0.id == tagId })

    // Remove tag from original array and place it according to the `order`.
    let removedTag = tags.remove(at: tagIndex!)
    tags.insert(removedTag, at: orderIndex)
}

// Print the result.
tags.forEach {
    print($0.name)
}

原始元素的顺序tagsCcc > Bbb > Aaa > Ddd > Eee. Bbb其中两个命名为和的元素Ddd应基于 排序order,即Bbb > Ddd。其余的应按字母顺序排列。换句话说,最终结果应该是Bbb > Ddd > Aaa > Ccc > Eee。虽然for上面的循环有效,但我怎样才能更有效地解决这个问题?

标签: arraysswift

解决方案


我会结合两段代码:

  1. HardCodedOrdering我的这个答案中,它使用固定排序(例如您的order数组)来派生对象的排序键。
  2. 使用此模式根据多个条件对对象进行排序:https ://stackoverflow.com/a/37612765/3141234

import Foundation

struct Tag: Identifiable {
    var id = UUID()
    var name: String
}

// Bbb > Ddd
let idOrdering = HardCodedOrdering(ordering:
    UUID(uuidString: "007D8DD7-7DF7-4937-BE53-C8CCE9C34A09")!,
    UUID(uuidString: "B1792EF4-CD4C-4437-90C2-37FE56D3A18F")!,
    sortUnspecifiedItems: .last
)

// Ccc > Bbb > Aaa > Ddd > Eee
let tags = [
    Tag(id: UUID(uuidString: "20FCD62B-97B8-4097-B659-29357EABE786")!, name: "Ccc"),
    Tag(id: UUID(uuidString: "007D8DD7-7DF7-4937-BE53-C8CCE9C34A09")!, name: "Bbb"),
    Tag(id: UUID(uuidString: "36FCEBF2-9912-4D67-A0F3-5EE1BF6EFE86")!, name: "Aaa"),
    Tag(id: UUID(uuidString: "B1792EF4-CD4C-4437-90C2-37FE56D3A18F")!, name: "Ddd"),
    Tag(id: UUID(uuidString: "463927D5-F6D8-4099-99FC-D3DE226B00C9")!, name: "Eee"),
]

let result = tags.sorted {
    (idOrdering.sortKey(for: $0.id), $0.name) <
    (idOrdering.sortKey(for: $1.id), $1.name)
}

result.forEach { print($0) }

推荐阅读