列表排序后怎样保留选中条目的身份:排序和删除后的稳定选中项·练习03
整理背包或关卡列表时,显示行号会随排序改变。如果用行号代替条目身份,排序以后高亮可能跳到另一件物品;记录稳定编号可以把显示位置和选中对象分开。
本篇使用一组可以手算或逐行复查的虚构游戏记录。先读清操作顺序与边界,再看完整过程;它不是某一款现有游戏的隐藏公式,也不要求读者安装工具。
规则与输入
八个条目各有唯一编号和分数,选中其中一个编号。操作可以升序、降序、删除指定编号或增加新编号;排序同分按编号升序,增加时放到末尾。选中编号被删后显示为空,之后不自动选择其他条目。
初始数据[[0, 5], [1, 5], [2, 4], [3, 0], [4, 0], [5, 3], [6, 8], [7, 1]],选中编号2 操作[['asc'], ['desc'], ['remove', 6], ['add', 8, 7], ['asc'], ['remove', 2], ['desc'], ['add', 9, 5], ['asc'], ['remove', 4], ['add', 10, 2], ['desc']]
逐步计算与结果
执行['asc']后,显示行从一开始,依次为[编号,分数][[3, 0], [4, 0], [7, 1], [5, 3], [2, 4], [0, 5], [1, 5], [6, 8]]。最初选中编号2,当前行号5;序号只表示当前布局位置,编号才表示原条目。
执行['desc']后,显示行从一开始,依次为[编号,分数][[6, 8], [0, 5], [1, 5], [2, 4], [5, 3], [7, 1], [3, 0], [4, 0]]。最初选中编号2,当前行号4;序号只表示当前布局位置,编号才表示原条目。
执行['remove', 6]后,显示行从一开始,依次为[编号,分数][[0, 5], [1, 5], [2, 4], [5, 3], [7, 1], [3, 0], [4, 0]]。最初选中编号2,当前行号3;序号只表示当前布局位置,编号才表示原条目。
执行['add', 8, 7]后,显示行从一开始,依次为[编号,分数][[0, 5], [1, 5], [2, 4], [5, 3], [7, 1], [3, 0], [4, 0], [8, 7]]。最初选中编号2,当前行号3;序号只表示当前布局位置,编号才表示原条目。
执行['asc']后,显示行从一开始,依次为[编号,分数][[3, 0], [4, 0], [7, 1], [5, 3], [2, 4], [0, 5], [1, 5], [8, 7]]。最初选中编号2,当前行号5;序号只表示当前布局位置,编号才表示原条目。
执行['remove', 2]后,显示行从一开始,依次为[编号,分数][[3, 0], [4, 0], [7, 1], [5, 3], [0, 5], [1, 5], [8, 7]]。最初选中编号2,当前行号为空;序号只表示当前布局位置,编号才表示原条目。
执行['desc']后,显示行从一开始,依次为[编号,分数][[8, 7], [0, 5], [1, 5], [5, 3], [7, 1], [3, 0], [4, 0]]。最初选中编号2,当前行号为空;序号只表示当前布局位置,编号才表示原条目。
执行['add', 9, 5]后,显示行从一开始,依次为[编号,分数][[8, 7], [0, 5], [1, 5], [5, 3], [7, 1], [3, 0], [4, 0], [9, 5]]。最初选中编号2,当前行号为空;序号只表示当前布局位置,编号才表示原条目。
执行['asc']后,显示行从一开始,依次为[编号,分数][[3, 0], [4, 0], [7, 1], [5, 3], [0, 5], [1, 5], [9, 5], [8, 7]]。最初选中编号2,当前行号为空;序号只表示当前布局位置,编号才表示原条目。
执行['remove', 4]后,显示行从一开始,依次为[编号,分数][[3, 0], [7, 1], [5, 3], [0, 5], [1, 5], [9, 5], [8, 7]]。最初选中编号2,当前行号为空;序号只表示当前布局位置,编号才表示原条目。
执行['add', 10, 2]后,显示行从一开始,依次为[编号,分数][[3, 0], [7, 1], [5, 3], [0, 5], [1, 5], [9, 5], [8, 7], [10, 2]]。最初选中编号2,当前行号为空;序号只表示当前布局位置,编号才表示原条目。
执行['desc']后,显示行从一开始,依次为[编号,分数][[8, 7], [0, 5], [1, 5], [9, 5], [5, 3], [10, 2], [7, 1], [3, 0]]。最初选中编号2,当前行号为空;序号只表示当前布局位置,编号才表示原条目。
删除选中对象后保持空状态,后面排序及加入不同编号都不会悄悄选中别的条目。
怎样独立复核
每一步先核对剩余编号及分数,再在当前显示序列中寻找被选编号的位置。找不到时必须为空,不能沿用之前行号。相同分数只影响相对排序规则,不会把两个编号合并为一个对象。
稳定编号只是此例的数据约定,不要求所有真实界面采取同一种删除后行为。产品可以选择下一项或父项,但应明确规定。本例也不模拟滚动和焦点;选中对象、键盘焦点与可见行可以是不同状态。
练习时可以只改变一个输入,再预测哪一步会最先改变。保留中间记录,检查空状态、相等数值和刚好落在边界的情况。最终结果碰巧相同,并不能证明两个过程等价;反过来,采用不同规则得出不同结果,也不应立即视作程序故障。