高效Swift数组比较
Efficient Swift Array Comparison
struct Area {
var name: String
var isSelected: Bool
}
我有两个列表:
- 列表一:它包含区域的完整列表。
- 列表二:它包含用户从列表一中选择的区域子集(但未设置选择状态)
我想做的是创建一个新的区域列表,其中包含两个列表中的项目,但如果列表一中的元素在列表二中,我想将 isSelected 属性 更新为 true。
我写了当前的方法,但它有缺陷且效率低下:
private func didGetCurrentUserSession(_ usersAreas: [Area]?, allAreas: [Area]){
guard let usersAreas = usersAreas else {return}
var newAreasList = [Area]()
for area in allAreas {
for userArea in usersAreas {
if userArea.name == area.name {
newAreasList.append(Area(name: area.name, isSelected: true))
break
}
}
newAreasList.append(Area(name: area.name, isSelected: false))
}
_loadingAreas.onNext(false)
_areas.onNext(newAreasList)
}
如有任何帮助,我们将不胜感激。更愿意使用非常 Swifty 的方法来完成此操作。
两种选择:对两个数组进行排序,或将一个数组转换为字典以便快速查找。不管你做什么,把它变成一个通用方法。
让我们获取用户区域的名称:
let userAreaNames = Set((usersAreas ?? []).map { [=10=].name })
映射其他区域
let newAreas = allAreas.map { area in
return Area(
name: area.name,
isSelected: userAreaNames.contains(area.name)
)
}
首先对数组进行排序以提高效率。
目前您的代码中的主要缺陷是错误的选定区域被附加到您的新数组,即使该区域的真实选定版本已经被附加。尝试这样的事情:
private func didGetCurrentUserSession(_ usersAreas: [Area]?, allAreas: [Area]){
guard let usersAreas = usersAreas else {return}
var newAreasList = [Area]()
var selected = Bool()
for area in allAreas {
for userArea in usersAreas {
if userArea.name == area.name {
newAreasList.append(Area(name: area.name, isSelected: true))
selected = true
break
}
}
if selected == false {
newAreasList.append(Area(name: area.name, isSelected: false))
} else {
selected = false
}
}
_loadingAreas.onNext(false)
_areas.onNext(newAreasList)
}
Sulthan 的回答很好,但是你的警卫声明使得他的设置过于复杂。相反,只需将构造更简单的集合放入捕获列表即可。
let newAreas = allAreas.map { [usersAreaNames = Set( usersAreas.map(\.name) )] in
Area(
name: [=10=].name,
isSelected: usersAreaNames.contains([=10=].name)
)
}
struct Area {
var name: String
var isSelected: Bool
}
我有两个列表:
- 列表一:它包含区域的完整列表。
- 列表二:它包含用户从列表一中选择的区域子集(但未设置选择状态)
我想做的是创建一个新的区域列表,其中包含两个列表中的项目,但如果列表一中的元素在列表二中,我想将 isSelected 属性 更新为 true。
我写了当前的方法,但它有缺陷且效率低下:
private func didGetCurrentUserSession(_ usersAreas: [Area]?, allAreas: [Area]){
guard let usersAreas = usersAreas else {return}
var newAreasList = [Area]()
for area in allAreas {
for userArea in usersAreas {
if userArea.name == area.name {
newAreasList.append(Area(name: area.name, isSelected: true))
break
}
}
newAreasList.append(Area(name: area.name, isSelected: false))
}
_loadingAreas.onNext(false)
_areas.onNext(newAreasList)
}
如有任何帮助,我们将不胜感激。更愿意使用非常 Swifty 的方法来完成此操作。
两种选择:对两个数组进行排序,或将一个数组转换为字典以便快速查找。不管你做什么,把它变成一个通用方法。
让我们获取用户区域的名称:
let userAreaNames = Set((usersAreas ?? []).map { [=10=].name })
映射其他区域
let newAreas = allAreas.map { area in
return Area(
name: area.name,
isSelected: userAreaNames.contains(area.name)
)
}
首先对数组进行排序以提高效率。
目前您的代码中的主要缺陷是错误的选定区域被附加到您的新数组,即使该区域的真实选定版本已经被附加。尝试这样的事情:
private func didGetCurrentUserSession(_ usersAreas: [Area]?, allAreas: [Area]){
guard let usersAreas = usersAreas else {return}
var newAreasList = [Area]()
var selected = Bool()
for area in allAreas {
for userArea in usersAreas {
if userArea.name == area.name {
newAreasList.append(Area(name: area.name, isSelected: true))
selected = true
break
}
}
if selected == false {
newAreasList.append(Area(name: area.name, isSelected: false))
} else {
selected = false
}
}
_loadingAreas.onNext(false)
_areas.onNext(newAreasList)
}
Sulthan 的回答很好,但是你的警卫声明使得他的设置过于复杂。相反,只需将构造更简单的集合放入捕获列表即可。
let newAreas = allAreas.map { [usersAreaNames = Set( usersAreas.map(\.name) )] in
Area(
name: [=10=].name,
isSelected: usersAreaNames.contains([=10=].name)
)
}