swift - 使用 swift 内置分区来管理数组中的元素
问题描述
iOS 14、斯威夫特 5.x
我从 2018 年开始观看了这个出色的 WWDC
https://developer.apple.com/videos/play/wwdc2018/223/
我写了一个形状编辑器......并且一直在尝试使用视频中的 Dave 所说的分区。我让前三个工作,但最后一个我不得不使用循环——我一生都无法弄清楚如何让它与分区一起工作。
有人可以看到我该怎么做吗?
第一种方法将选定的对象移动到列表的末尾,效果很好。
func bringToFrontEA() {
let subset = objects.partition(by: { $0.selected })
let selected = objects[subset...]
let unselected = objects[..<subset]
let reordered = unselected + selected
objects = Array(reordered)
}
第二种方法将选定对象移动到列表的前面。完美运行。
func sendToBackEA() {
let subset = objects.partition(by: { !$0.selected })
let selected = objects[subset...]
let unselected = objects[..<subset]
let reordered = unselected + selected
objects = Array(reordered)
}
第三种方法将元素仅移回列表中的一个元素。完美运行。
func sendBackEA() {
if let i = objects.firstIndex(where: { $0.selected }) {
if i == 0 { return }
let predecessor = i - 1
let shapes = objects[predecessor...].partition(by: { !$0.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 { $0.element.selected == true }.map{$0.offset}
for i in indexes {
if objects[i+1].unused {
return
}
objects.swapAt(i+1, i)
}
}
Objects 是一个形状数组,其属性指示它是否被选中。我想通过使用分区来交换最后一个方法中的循环,就像我在前三个中所做的那样。它需要适用于一种或多种选定的形状。
解决方案
看 WWDC 视频,看来你叫sendBackEA
什么就是 WWDC 叫bringForward
什么,你叫bringForwardEA
什么就是 WWDC 叫什么sendBack
。
就像您如何将第一个选定元素向前移动一个索引(索引减小) in sendBackEA
,然后将所有其他选定元素移动到该第一个选定元素之后。bringForwardEA
应该做相反的事情:将最后一个选定元素向后移动一个索引(索引增加),然后将所有其他选定元素移动到最后一个选定元素之前。(见视频中大约 19:10)
您似乎通过尝试将所有选定索引的索引增加 1 感到困惑。这显然不能用分区来完成。
另请注意,partition(by:)
已经修改了集合,不需要获取每个分区,然后重新组合。
你的 4 个方法可以这样写:
func bringToFrontEA() {
objects.partition(by: { $0.selected })
}
func sendToBackEA() {
objects.partition(by: { !$0.selected })
}
func sendBackEA() {
if let i = objects.indices.first(where: { objects[$0].selected }) {
if i == 0 { return }
let predecessor = i - 1
objects[predecessor...].partition(by: { !$0.selected })
}
}
func bringForwardEA() {
if let i = objects.indices.last(where: { objects[$0].selected }) {
if i == objects.indices.last { return }
let successor = i + 1
objects[...successor].partition(by: { !$0.selected })
}
}
sendBackEA
注意和之间的对称性bringForwardEA
。
推荐阅读
- laravel - 如何在 Docker 上设置 Laravel 以进行本地开发?
- java - 如何在java中使用double作为函数?
- tensorflow - 如何使用 tensorflow (Keras) 中给出的注意力或附加注意力层来完成 NER 任务?
- r - 使用 R 条形图函数分组条形图
- java - 我可以使用 JButton 作为构造函数的参数吗
- python - 使用正则表达式 python 在标签之间提取文本
- javascript - 如何更改材料输入文本样式反应js
- javascript - 如果在 javascript .replace 中使用,如何在 RegEx 中定位破折号或连字符?
- html - 用没有 ID 的元素预填充 html 表单
- python-3.x - 跨共享内存在 Gstreamer 管道中同步或映射帧