Swift 在对象数组中搜索值(映射)的更好方法
我有一个名为Room的类,我在其中存储关于我家中某个特定房间的信息(房间的名称、图像等)。在我的主ViewController中,我创建了一个房间数组,并为它们指定了一些值。稍后,我想在这个房间数组中搜索名为“自习室”的房间Swift 在对象数组中搜索值(映射)的更好方法,swift,Swift,我有一个名为Room的类,我在其中存储关于我家中某个特定房间的信息(房间的名称、图像等)。在我的主ViewController中,我创建了一个房间数组,并为它们指定了一些值。稍后,我想在这个房间数组中搜索名为“自习室”的房间 func findARoom(named room: String) -> Room { for i in 0..<rooms.count { if rooms[i].roomName == room {
func findARoom(named room: String) -> Room {
for i in 0..<rooms.count {
if rooms[i].roomName == room {
return rooms[i]
}
}
}
视图控制器:
import UIKit
class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, RoomCellDelegate, MQTTModelDelegate {
var server = [MQTTModel()]
let cellId = "cellId"
var rooms: [Room] = [Room]()
var roomTableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
createRoomArray()
findARoom(named: "Study Room")
}
// Setting up the array of rooms
func createRoomArray() {
rooms.append(Room(roomName: "Living Room", roomImage: UIImage(named: "Living_Room")!, port: 48712))
rooms.append(Room(roomName: "Study Room", roomImage: UIImage(named: "Study_Room")!, port: 1883))
rooms.append(Room(roomName: "Bedroom", roomImage: UIImage(named: "Bedroom")!, port: 1883))
}
func findARoom(named room: String) -> Room {
for i in 0..<rooms.count {
if rooms[i].roomName == room {
return rooms[i]
}
}
}
}
导入UIKit
类MainViewController:UIViewController、UITableViewDelegate、UITableViewDataSource、RoomCellDelegate、MQTTModelDelegate{
var server=[MQTTModel()]
let cellId=“cellId”
var房间:[房间]=[房间]()
var roomTableView=UITableView()
重写func viewDidLoad(){
super.viewDidLoad()
createRoomArray()
findARoom(命名为“自习室”)
}
//设置房间阵列
func createRoomArray(){
附加(房间(房间名称:“客厅”,房间图像:UIImage(名称:“客厅”)!,端口:48712))
房间。附加(房间(房间名称:“书房”,房间图像:UIImage(名称:“书房”)!,端口:1883))
房间。追加(房间(房间名称:“卧室”,房间图像:UIImage(名称:“卧室”)!,端口:1883))
}
func findARoom(命名房间:String)->room{
对于0中的i..您可以尝试
if let res = rooms.first(where:{ $0.roomName == "Study Room" }) {
}
你可以试试
if let res = rooms.first(where:{ $0.roomName == "Study Room" }) {
}
如果你想在不在O(1)时间内迭代整个数组,就可以搜索<代码>房间,你应该考虑使用<代码>字典<代码>而不是一个数组,它类似于C++中的映射。
您的ViewController代码需要修改如下:
import UIKit
class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, RoomCellDelegate, MQTTModelDelegate {
var server = [MQTTModel()]
let cellId = "cellId"
var rooms: [String: Room] = [String: Room]() // Declare the dictionary
var roomTableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
createRoomDictionary()
findARoom(named: "Study Room")
}
// Setting up the dictionary of rooms
func createRoomDictionary() {
rooms["Living Room"] = Room(roomName: "Living Room", roomImage: UIImage(named: "Living_Room")!, port: 48712)
rooms["Study Room"] = Room(roomName: "Study Room", roomImage: UIImage(named: "Study_Room")!, port: 1883)
rooms["Bedroom"] = Room(roomName: "Bedroom", roomImage: UIImage(named: "Bedroom")!, port: 1883)
}
func findARoom(named room: String) -> Room {
return rooms[room]
}
}
如果你想在不在O(1)时间内迭代整个数组,就可以搜索<代码>房间,你应该考虑使用<代码>字典<代码>而不是一个数组,它类似于C++中的映射。
您的ViewController代码需要修改如下:
import UIKit
class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, RoomCellDelegate, MQTTModelDelegate {
var server = [MQTTModel()]
let cellId = "cellId"
var rooms: [String: Room] = [String: Room]() // Declare the dictionary
var roomTableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
createRoomDictionary()
findARoom(named: "Study Room")
}
// Setting up the dictionary of rooms
func createRoomDictionary() {
rooms["Living Room"] = Room(roomName: "Living Room", roomImage: UIImage(named: "Living_Room")!, port: 48712)
rooms["Study Room"] = Room(roomName: "Study Room", roomImage: UIImage(named: "Study_Room")!, port: 1883)
rooms["Bedroom"] = Room(roomName: "Bedroom", roomImage: UIImage(named: "Bedroom")!, port: 1883)
}
func findARoom(named room: String) -> Room {
return rooms[room]
}
}
如前所述,您可以使用,例如:
但是你说:
我希望能够以相同的方式调用findARoom()
函数,但不能遍历整个数组
不幸的是,确实执行了一个for
循环。只需查看该方法。它仍然是O(n),就像您自己的实现一样
如果您是说您不想为
循环编写自己的,那么first
(或类似)只是编写相同内容的一种更简洁的方法,但要意识到它并不比您的方法更有效
如果您真的想享受哈希性能,可以构建一个字典:
let rooms: [Room] = ...
let dictionary = Dictionary(grouping: rooms, by: { $0.roomName })
生成的词典
是一个[字符串:[Room]]
现在,当您在this字典中查找房间时,您将享受哈希键性能:
if let room = dictionary["Study Room"]?.first { ... }
恕我直言,这种字典结构在这样的应用程序中是不值得的,而且first(where:)
是一个非常好、简洁的解决方案。但是如果你真的不想让它循环并且真的需要O(1)性能,你应该知道first
将无法实现这一点。正如已经指出的,你可以使用,例如:
但是你说:
我希望能够以相同的方式调用findARoom()
函数,但不能遍历整个数组
不幸的是,确实执行了一个for
循环。只需查看该方法。它仍然是O(n),就像您自己的实现一样
如果您是说您不想为
循环编写自己的,那么first
(或类似)只是编写相同内容的一种更简洁的方法,但要意识到它并不比您的方法更有效
如果您真的想享受哈希性能,可以构建一个字典:
let rooms: [Room] = ...
let dictionary = Dictionary(grouping: rooms, by: { $0.roomName })
生成的词典
是一个[字符串:[Room]]
现在,当您在this字典中查找房间时,您将享受哈希键性能:
if let room = dictionary["Study Room"]?.first { ... }
恕我直言,这种字典结构在这样的应用程序中是不值得的,而且first(where:)
是一个非常好的简洁解决方案。但是如果你真的不想让它循环,并且真的需要O(1)性能,你应该知道first
将无法实现这一点。对于大多数事情,使用数组。first(where:{$0.name==“stringToMatch”}
将非常快
我刚刚做了一个快速的基准测试,在我现在非常低端的原始iPad Air上运行时关闭了优化功能,有100000个结构数组,其中包含一个名称字段,first(其中:)
在大约0.026秒内匹配了一个项目。你可能看不到那么大的延迟。(即搜索在数组中随机索引处出现的项。强制字符串与数组中的最后一个元素匹配会将第一个(其中:)
的速度降低到0.047秒左右(≈1/20秒)
编辑:
这是我用来先计时的代码(其中:)
:
对于大多数情况,使用array.first(其中:{$0.name==“stringToMatch”}
将非常快
我刚刚做了一个快速的基准测试,在我现在非常低端的原始iPad Air上运行时关闭了优化功能,有100000个结构数组,其中包含一个名称字段,first(其中:)
在大约0.026秒内匹配了一个项目。你可能看不到那么大的延迟。(即搜索在数组中随机索引处出现的项。强制字符串与数组中的最后一个元素匹配会将第一个(其中:)
的速度降低到0.047秒左右(≈1/20秒)
编辑:
这是我用来先计时的代码(其中:)
:
谢谢,字典就是我要找的。你能详细解释一下为什么你认为字典结构在这种情况下不值得吗?当数组太小以至于循环不重要时,它会占用额外的内存吗?还是其他什么?再次感谢你花时间回答。Exactl