重新排序具有多个订单标准的商品

时间:2012-10-22 20:35:18

标签: sorting

方案

  • 照片列表
  • 每张照片都有以下属性
    • id
    • sequence_number
    • main_photo_bit
  • 第一张照片的main_photo_bit设置为1(所有其他照片均为0
  • 照片按sequence_number任意
  • 排序
  • 主照片不一定具有最低sequence_number(排序前)

见下表:

id, sequence_number, main_photo_bit
1   10               1             
2    5               0             
3   20               0             

现在您想通过更改序列号和主要照片位来更改顺序。

排序后的要求:

  • 第一张照片的sequence_number未更改
  • 第一张照片的sequence_number是最低的
  • 尽可能少的变化

示例:

示例#1(第二张照片转到第一个位置):

id, sequence_number, main_photo_bit
2   10               1             
1   15               0             
3   20               0             

发生了什么:

  • ID 1:新sequence_numbermain_photo_bit设置为0
  • ID 2:旧的第一张照片(ID 2)sequence_numbermain_photo_bit设置为1
  • id 3:没有任何反应

示例#2(第三张照片到第一张位置):

id, sequence_number, main_photo_bit
3   10               1             
1   20               0             
2   30               0             

发生了什么:

  • ID 1:新sequence_number比第一张照片大main_photo_bit0
  • ID 2:新增sequence_number比新生成的第二个sequence_number
  • 更大
  • ID 3:旧的第一张照片sequence_numbermain_photo_bit设置为1

计算保存新订单所需步骤的最佳方法是什么?

编辑:
我希望尽可能减少更新的原因是因为我想将它同步到外部服务,这是一项非常昂贵的操作。
我已经有了算法的工作原型,但在一些边缘情况下失败了。因此,不是修补它(这可能会起作用 - 但它会变得比现在更复杂),我想知道是否还有其他(更好)的方法来做到这一点。
在我的版本中(简而言之)它会对照片进行排序(更改sequence_number),并交换main_photo_bit,但这还不足以解决所有情况。

2 个答案:

答案 0 :(得分:3)

根据我的理解,一个好的解决方案不仅可以最大限度地减少变更(因为更新是昂贵的操作),而且还会尽量减少未来的变化,因为更多和更多照片被重新排序。我首先添加一个临时字段dirty,以指示行是否必须更改:

id, sequence_number, main_photo_bit, dirty
 1         10               1        false
 2          5               0        false
 3         20               0        false
 4         30               0        false
 5         31               0        false
 6         33               0        false

如果有sequence_number小于第一行的行,则肯定必须更改(要么获得更高的数字,要么成为第一个)。我们将它们标记为dirty

id, sequence_number, main_photo_bit, dirty
 2          5               0        true

(跳过此步骤,如果第一步具有最低sequence_number并不重要)

现在让我们看一下照片列表,因为它们应该在结果中(根据问题,只有一张照片更改了地点,从任何地方到任何地方)。肮脏的粗体:

  

[1, 2 ,3,4,5,6]#原始订购

     

[ 2 1 ,3,4,5,6]#例1:第2到第1位

     

[ 3 1 2 ,4,5,6]#例2:第3到第1位

     

[1, 2 ,4, 3 ,5,6]#例3:第3至第4位

     

[1, 3 2 ,4,5,6]#例4:第3到第2位

要做的第一件事是确保第一个元素具有最低sequence_number。如果它没有改变位置,那么它有定义,否则旧的第一个应该标记为脏,清除main_photo_bit,新的应该接收这些值。

此时,第一个元素应该有一个固定的sequence_number,并且每个脏元素都可以随意更改其值(因为它无论如何都必须更改,因此最好更改一个有用的值) 。在继续之前,我们必须确保可能仅通过更改脏行来解决它,或者更多行也必须被弄脏。这只是确定每对干净行之间的间隔是否足够大以适应它们之间的脏行数的问题:

[10, D, 20, 30, 31, 33]   # Original ordering (the first is dirty, but fixed)

[10, D, 20, 30, 31, 33]   # Example 1: 2nd to 1st place (ok: 10 < ? < 20)
[10, D, D, 30, 31, 33]    # Example 2: 3rd to 1st place (ok: 10 < ? < ? < 30)
[10, D, 30, D, 31, 33]    # Example 3: 3rd to 4th place (NOT OK: 30 < ? < 31)
  [10, D, 30, D, D, 33]   #   must mark 5th as dirty too (ok: 30 < ? < ? < 33)
[10, D, D, 30, 31, 33]    # Example 4: 3rd to 2nd place (ok)

现在只需要将新的sequence_number分配给脏行。一个天真的解决方案是只增加前一个,但更好的方法是将它们设置为尽可能等间距。通过这种方式,未来的重新排序需要更少的更改(换句话说,为了避免像示例3那样的问题,因为有些sequence_number彼此距离太近,因此必须更新所需的行数。 ):

  

[ 10 15 ,20,30,31,33]#示例1:第2到第1位

     

[ 10 16 23 ,30,31,33]#示例2:第3到第1位

     

[10, 20 ,30, 31 32 ,33]#例3:第3至第4位

     

[10, 16 23 ,30,31,33]#例4:第3至第2位


奖励:如果您真的想要将解决方案推向极限,请执行两次计算 - 一次移动照片,另一次将其固定并移动周围的照片 - 并查看哪一个导致变化少了。以示例3A为例,我们将其视为“第4至第3位”(相同的排序结果,但不同的更改),而不是“第3至第4位”:

  

[1, 2 4 ,3,5,6]#例3A:第4至第3位

     

[10,D,D,20,31,33]#(ok:10&lt;?&lt;?&lt; 20)

     

[10, 13 16 ,20,31,33]#少改变一次

在大多数情况下,它可以完成(例如:第2到第4位= =第3 /第4到第2 /第3位),无论增加的复杂性是否值得获得小额收益,由您决定。< / p>

答案 1 :(得分:1)

使用链接列表而不是序列号。然后,您可以从列表中的任何位置删除图片,并将其重新插入列表中的任何位置,您只需要在数据库文件中更改3行。主要照片位应该是不必要的,第一张照片是通过没有任何指针隐式定义的。

id      next
1       3
2       1
3       

顺序是:2,1,3

用户将图片3移动到位置1:

id      next
1       
2       1
3       2

新订单是:3,2,1