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

问题描述 投票:2回答:2

场景:

  • 照片列表
  • 每张照片都有以下属性 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
  • 身份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,但它不足以解决每个场景。

sorting
2个回答
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_numbers分配给脏行。一个天真的解决方案是只增加前一个,但更好的方法是将它们设置为尽可能相等。这样,未来的重新排序需要更少的更改(换句话说,为了避免像示例3那样的问题,因为一些sequence_numbers彼此太接近,因此必须更新比必要更多的行)的问题更好:

[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]#(好的:10 <?<?<20)

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

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


1
投票

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

id      next
1       3
2       1
3       

顺序是:2,1,3

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

id      next
1       
2       1
3       2

新订单是:3,2,1

© www.soinside.com 2019 - 2024. All rights reserved.