使用 swift 内置分区来管理数组中的元素
Using swift built in partition to manage elements in an array
iOS 14, Swift 5.x
我从 2018 年开始观看这个优秀的 WWDC
https://developer.apple.com/videos/play/wwdc2018/223/
我写了一个形状编辑器...并且一直在尝试使用分区,正如 Dave 在视频中所说的那样。我让前三个工作,但最后一个我不得不使用循环 - 我无法终生弄清楚如何让它与分区一起工作。
有人能看到我该怎么做吗?
第一种方法将所选对象移动到列表末尾,效果很好。
func bringToFrontEA() {
let subset = objects.partition(by: { [=11=].selected })
let selected = objects[subset...]
let unselected = objects[..<subset]
let reordered = unselected + selected
objects = Array(reordered)
}
第二种方法将选中的对象移动到列表的前面。完美运行。
func sendToBackEA() {
let subset = objects.partition(by: { ![=12=].selected })
let selected = objects[subset...]
let unselected = objects[..<subset]
let reordered = unselected + selected
objects = Array(reordered)
}
第三种方法仅将元素移回列表中的一个元素。完美运行。
func sendBackEA() {
if let i = objects.firstIndex(where: { [=13=].selected }) {
if i == 0 { return }
let predecessor = i - 1
let shapes = objects[predecessor...].partition(by: { ![=13=].selected })
let slice = objects[predecessor...]
let row = objects[..<predecessor]
let selected = Array(slice[..<shapes])
let unselected = Array(slice[shapes...])
objects = row + selected + unselected
}
}
最后一种方法在列表中向前移动元素,效果很好...但与其他方法不同,它不会像 WWDC 视频中描述的那样缩放。
func bringForwardEA() {
let indexes = objects.enumerated().filter { [=14=].element.selected == true }.map{[=14=].offset}
for i in indexes {
if objects[i+1].unused {
return
}
objects.swapAt(i+1, i)
}
}
Objects 是一个形状数组,带有一个 属性 指示它是否被选中。我想像在前三个方法中那样使用分区来交换最后一个方法中的循环。它需要适用于一个或多个选定的形状。
看WWDC视频,好像你说的sendBackEA
是WWDC说的bringForward
,你说的bringForwardEA
是WWDC说的[=14] =].
就像你将第一个选中的元素向前移动一个索引(索引递减)在sendBackEA
,然后移动所有其他选定元素立即在第一个选定元素之后。 bringForwardEA
应该相反:将 last 选定元素 向后 移动一个索引(索引增加),然后移动所有其他选定元素立即 在 最后一个选定元素之前。 (请参阅视频中的大约 19:10)
您似乎对尝试将所有选定索引的索引增加 1 感到困惑。这显然不能用一般的分区来完成。
另请注意,partition(by:)
已经修改了集合,您不需要获取每个分区,然后重新组合。
你的4个方法可以这样写:
func bringToFrontEA() {
objects.partition(by: { [=10=].selected })
}
func sendToBackEA() {
objects.partition(by: { ![=10=].selected })
}
func sendBackEA() {
if let i = objects.indices.first(where: { objects[[=10=]].selected }) {
if i == 0 { return }
let predecessor = i - 1
objects[predecessor...].partition(by: { ![=10=].selected })
}
}
func bringForwardEA() {
if let i = objects.indices.last(where: { objects[[=10=]].selected }) {
if i == objects.indices.last { return }
let successor = i + 1
objects[...successor].partition(by: { ![=10=].selected })
}
}
注意 sendBackEA
和 bringForwardEA
之间的对称性。
iOS 14, Swift 5.x
我从 2018 年开始观看这个优秀的 WWDC
https://developer.apple.com/videos/play/wwdc2018/223/
我写了一个形状编辑器...并且一直在尝试使用分区,正如 Dave 在视频中所说的那样。我让前三个工作,但最后一个我不得不使用循环 - 我无法终生弄清楚如何让它与分区一起工作。
有人能看到我该怎么做吗?
第一种方法将所选对象移动到列表末尾,效果很好。
func bringToFrontEA() {
let subset = objects.partition(by: { [=11=].selected })
let selected = objects[subset...]
let unselected = objects[..<subset]
let reordered = unselected + selected
objects = Array(reordered)
}
第二种方法将选中的对象移动到列表的前面。完美运行。
func sendToBackEA() {
let subset = objects.partition(by: { ![=12=].selected })
let selected = objects[subset...]
let unselected = objects[..<subset]
let reordered = unselected + selected
objects = Array(reordered)
}
第三种方法仅将元素移回列表中的一个元素。完美运行。
func sendBackEA() {
if let i = objects.firstIndex(where: { [=13=].selected }) {
if i == 0 { return }
let predecessor = i - 1
let shapes = objects[predecessor...].partition(by: { ![=13=].selected })
let slice = objects[predecessor...]
let row = objects[..<predecessor]
let selected = Array(slice[..<shapes])
let unselected = Array(slice[shapes...])
objects = row + selected + unselected
}
}
最后一种方法在列表中向前移动元素,效果很好...但与其他方法不同,它不会像 WWDC 视频中描述的那样缩放。
func bringForwardEA() {
let indexes = objects.enumerated().filter { [=14=].element.selected == true }.map{[=14=].offset}
for i in indexes {
if objects[i+1].unused {
return
}
objects.swapAt(i+1, i)
}
}
Objects 是一个形状数组,带有一个 属性 指示它是否被选中。我想像在前三个方法中那样使用分区来交换最后一个方法中的循环。它需要适用于一个或多个选定的形状。
看WWDC视频,好像你说的sendBackEA
是WWDC说的bringForward
,你说的bringForwardEA
是WWDC说的[=14] =].
就像你将第一个选中的元素向前移动一个索引(索引递减)在sendBackEA
,然后移动所有其他选定元素立即在第一个选定元素之后。 bringForwardEA
应该相反:将 last 选定元素 向后 移动一个索引(索引增加),然后移动所有其他选定元素立即 在 最后一个选定元素之前。 (请参阅视频中的大约 19:10)
您似乎对尝试将所有选定索引的索引增加 1 感到困惑。这显然不能用一般的分区来完成。
另请注意,partition(by:)
已经修改了集合,您不需要获取每个分区,然后重新组合。
你的4个方法可以这样写:
func bringToFrontEA() {
objects.partition(by: { [=10=].selected })
}
func sendToBackEA() {
objects.partition(by: { ![=10=].selected })
}
func sendBackEA() {
if let i = objects.indices.first(where: { objects[[=10=]].selected }) {
if i == 0 { return }
let predecessor = i - 1
objects[predecessor...].partition(by: { ![=10=].selected })
}
}
func bringForwardEA() {
if let i = objects.indices.last(where: { objects[[=10=]].selected }) {
if i == objects.indices.last { return }
let successor = i + 1
objects[...successor].partition(by: { ![=10=].selected })
}
}
注意 sendBackEA
和 bringForwardEA
之间的对称性。