允许对对象重新排序的算法,同时只需要更新恒定数量的对象位置

2024-04-25

我有一大堆对象,我希望根据它们的一个属性来保持顺序。

作为一个例子,我们假设一个对象可能看起来像:

var myObject = {
    id: 'c_1',
    position: 0 
}

有序集合的简单实现如下所示:

[{
    id: 'c_1',
    position: 0 
}, {
    id: 'c_2',
    position: 1
}, {
    id: 'c_3',
    position: 2 
}, {
    id: 'c_4',
    position: 3 
}, {
    id: 'c_5',
    position: 4 
}]

这是一个幼稚的实现的原因是,如果“c_4”希望在“c_1”和“c_2”之间移动,那么“c_2”、“c_3”、“c_4”和“c_5”的位置必须全部更新为容纳。这意味着,平均而言,对于对象数组的任何给定重新排序,N/2 + 1 个元素将受到影响。

我目前提出的解决方案并不那么幼稚,但也有其自身的缺陷。

我没有将每个元素直接相邻放置(即 0、1、2、3、4),而是在每个元素之间留下“足够大”的间隙:

[{
    id: 'c_1',
    position: 10000 
}, {
    id: 'c_2',
    position: 20000
}, {
    id: 'c_3',
    position: 30000 
}, {
    id: 'c_4',
    position: 40000 
}, {
    id: 'c_5',
    position: 50000
}]

现在,如果“c_4”希望在“c_1”和“c_2”之间移动,则其位置将设置为其两个提议的新邻居的中点。 “c_4”的位置为 15000,不需要影响其他元素。

不过,在足够大量的重新排序 (log(10000) = 13) 后,该解决方案开始崩溃,并且一旦遇到这种情况,就需要重新索引数组。

我想知道是否有另一种更优雅的解决方案来解决我的困境?

当我输入此内容时,我意识到我可以停止期望位置是整数,并允许它变成双精度数,这将允许任何两个给定元素之间有近乎无限数量的位置。也许这是正确的选择,但这实际上只是我的非幼稚实现的重新哈希。


这些是问题的步骤

  1. 数据的初始状态,包含重要索引的列表
  2. 更改列表中项目的索引
  3. 更新列表中所有项目的操作
  4. 数据的最终状态

至少有 3 种方法可以在客户端和服务器之间同步 #1 和 #4,我将在下面概述。请注意,我不会比较这三个选项的计算强度。听起来,处理速度不是您最关心的问题,而是带宽是。考虑到这一点,以下是三个选择:

方法一:发送最终状态

第一种方法是最明显的方法,也是您遇到问题的方法,是通过传递 #4 来更新服务器。随着您的列表变长,这将成为发送的相当大的有效负载。

Pros

  • #3 执行一次
  • 它适用于最常见的 HTTP 动词,例如 POST
  • 这是最明显的;很容易理解发生了什么

Cons

  • 正如您所指出的,随着列表的增长,您通过线路发送的数据会变得非常大

方法二:仅发送更改

第二种选择将带宽降低到绝对最小值。为此,您可以通过线路传递#2 并在服务器上执行#3。这会重复该操作(我想您仍然希望在客户端上执行它,而不是等待服务器的响应),但将带宽使用保持在最低限度。

这可能如下所示:

{
  oldIndex: 2134
  newIndex: 54
}

这为服务器提供了执行 #3 和执行 #4 所需的一切。这很容易扩展到n通过创建按顺序执行的操作列表来进行操作,从而产生n更新中的对象。

Pros

  • 带宽可能是最小的

Cons

  • 客户端和服务端重复操作逻辑,不太DRY
  • 服务器执行更多计算
  • 它是专有的,不像第一种方法那样简单的 API 端点

方法三:JSONPatch

第三个选项是使用JSON 补丁规范 https://www.rfc-editor.org/rfc/rfc6902生成补丁发送到服务器。单个移动操作的 JSON 补丁产生n+1物体,其中n = Math.abs(oldIndex - newIndex).

例如,

给定初始数组

[a, b, c, d, e, f, g, h, i, j]

和操作

{
  oldIndex: 5
  newIndex: 2
}

上面的算法显示 JSONPatch 将有 5-2+1,即 4 个对象。这些对象是:

[
  {"op":"replace","path":"/5","value":"e"},
  {"op":"replace","path":"/4","value":"d"},
  {"op":"replace","path":"/3","value":"c"},
  {"op":"replace","path":"/2","value":"f"}
]

如果您选择使用 JSONPatch 我建议您使用类似的库JSON 补丁 https://github.com/Starcounter-Jack/JSON-Patch来处理它。

Pros:

  • 处理的不仅仅是动作
  • 没有库可以处理所有的边缘情况(我在 JSON-Patch 上有几个关于失败情况的未解决问题)

Cons:

  • 比仅仅传递操作本身更多的带宽
  • 潜在的更多计算
  • 需要额外的库
  • 取决于 HTTP PATCH 动词
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

允许对对象重新排序的算法,同时只需要更新恒定数量的对象位置 的相关文章

  • 在二维平面中找到距离 P 点最近的 K 个点

    资料来源 亚马逊面试问题 解决方案1制作大小为 K 的堆并按最小距离收集点O NLogK 复杂 解决方案2 取大小为 N 的数组并按距离排序 应该使用QuickSort 霍尔修改 取前 K 点作为答案 这太复杂了 NlogN 但可以优化到近
  • 获取无平方数的列表

    获得该值的一种方法是自然数 1 n 我们对每个因子进行因式分解 看看它们是否有重复的质因数 但这对于大的情况来说会花费很多时间n 那么有没有更好的方法从 1 中获取无平方数n 您可以使用埃拉托斯特尼筛法的修改版本 取一个布尔数组 1 n 预
  • 在 O(n) 时间内运行的指数乘法算法?

    我正在读一本算法教科书 我被这个问题难住了 假设我们要计算值 x y 其中 x 和 y 为正数 分别具有 m 和 n 位的整数 解决该问题的一种方法是执行 y 1 乘以 x 你能给出一个仅使用 O n 乘法步骤的更有效的算法吗 这会是一个分
  • 给定与总和匹配的长度的唯一 3 位数字 (-1,0,1) 序列的数量

    假设您有一个长度为 n 即空格数 的垂直游戏板 你有一个三面骰子 有以下选项 前进一 停留和后退 如果您低于或高于棋盘游戏空间的数量 则该游戏无效 一旦到达棋盘末端 唯一有效的动作就是 停留 给定确切的骰子投掷次数 t 是否可以通过算法计算
  • 当目标是查找某个字符串的所有出现情况时,KMP 最坏情况的复杂度是多少?

    我还想知道哪种算法在查找另一个字符串中所有出现的字符串时具有最坏情况的复杂性 博耶 摩尔算法似乎具有线性时间复杂度 KMP 算法在查找字符串中所有出现的模式时具有线性复杂度 如 Boyer Moore 算法1 如果您尝试在 aaaaaaaa
  • 检查数独字段的很酷的算法?

    有谁知道一个简单的算法来检查数独配置是否有效 我想出的最简单的算法是 对于大小为 n 的板 伪代码 for each row for each number k in 1 n if k is not in the row using ano
  • 4 x 3 锁图案

    我遇到了这个 它要求计算在 4x3 网格中可以制作特定长度的锁定图案的方式数 并遵循规则 可能有些点不能包含在路径中 有效的模式具有以下属性 图案可以使用第一次接触的点序列来表示 与绘制图案的顺序相同 从 1 1 到 2 2 的图案与图案不
  • 如何使用KDTrees实现最近邻搜索?

    所以 我正在实施一个KD Tree http en wikipedia org wiki Kd tree进行最近邻搜索 我已经构建了树部分 但我认为我没有完全理解搜索部分 关于遍历树来搜索邻居 维基百科文章如下 Starting with
  • 如何设置K-means openCV c++的初始中心

    我正在尝试使用 OpenCv 和 Kmeans 对图像进行分割 我刚刚实现的代码如下 include opencv2 objdetect objdetect hpp include opencv2 highgui highgui hpp i
  • 如何在Scala中实现尾递归快速排序

    我写了一个递归版本 def quickSort T xs List T p T T gt Boolean List T xs match case Nil gt Nil case gt val x xs head val left righ
  • 合并字符数组中的最小重复次数

    假设我有两个数组 我想合并它们 以便合并后的数组具有最小重复次数 例如 x x 是重复 arr1 x d d m f m arr2 d d x f f m 唯一的条件是在合并数组中 元素来自arr1 and arr2必须出现在各自的订单中a
  • 反转二进制网络

    如何反转二元方程 以便找到哪些输入将产生给定的输出 Example Inputs i0 through i8 Outputs o0 through o8 Operators XOR AND 二元方程 1 i0 1 i1 0 i2 1 i3
  • Java:如何实现3和?

    我正在研究 3 Sum 来自己实现它 并遇到了以下规则的实现 给定一个由 n 个整数组成的数组 S S 中是否存在满足 a b c 0 的元素 a b c 查找数组中所有总和为零的唯一三元组 注意 三元组 a b c 中的元素必须按非降序排
  • 搜索/排序算法 - 是否有类似 GoF 的列表?

    我是一名自学成才的开发人员 坦率地说 我不太擅长找出在任何特定情况下使用哪种搜索或排序算法 我只是想知道是否有设计模式 esque 列出了以太坊中可用的常见算法 供我添加书签 就像是 算法名称 带有别名 如果有的话 它解决的问题 大O成本
  • 用 Java 创建迷宫求解算法

    我被分配了用 Java 创建迷宫求解器的任务 这是任务 Write an application that finds a path through a maze The maze should be read from a file A
  • 快速求解子集和

    考虑这种解决子集和问题的方法 def subset summing to zero activities subsets 0 for activity cost in activities iteritems old subsets sub
  • 固定大小集以包含给定集的最大数量

    我有大约 1000 组尺寸 1 4 1 3 3 5 6 4 5 6 7 5 25 42 67 100 是否有可能找到包含最大数量的给定集合的大小为 20 的集合 检查每一个100 80 20 集 效率低下 我不太确定这是 NP 完全的 考虑
  • 找到一系列间隔的最有效分组

    我有一个应用程序 其中有一系列不重叠的固定宽度间隔 每个间隔都有一个给定的键 每个间隔具有相同的宽度 并且可以存在连续的间隔 本质上 我想以最小化单独间隔的数量的方式对间隔和键进行分组 这可以通过合并具有相同键的连续间隔或查找匹配间隔并将它
  • 点集子集的最小周长凸包

    给定平面上的 n 个点 没有 3 个共线 给定数字 k 找到 k 个点的子集 使得 k 个点的凸包在 k 个点的子集的任何凸包中具有最小周长 我可以想到一个简单的方法 运行时间为 O n k k log k 找到大小为 k 的每个子集的凸包
  • 无需构建树即可预测霍夫曼压缩比

    我有一个二进制文件 我知道其中每个符号出现的次数 如果我要使用霍夫曼算法压缩它 我需要预测压缩文件的长度 我只对假设的输出长度感兴趣 而不对单个符号的代码感兴趣 因此构建霍夫曼树似乎是多余的 作为一个例子 我需要得到类似的东西 包含 4 个

随机推荐

  • 新 Maven/Spring MVC 项目的最小 pom.xml 文件

    我对 Maven 和 Spring MVC 完全陌生 我想做的是使用 Maven 设置一个新的 Spring MVC 项目 希望这句话有意义 并使用 Eclipse 在 Tomcat 上运行我的 Web 应用程序 我正在按照此链接上的教程进
  • 为什么 Logstash 需要这么长时间才能启动/加载?

    Edit 我更改了标题 因为问题不是我最初想象的那样 事实是 logstash 需要超过一分钟开始 这可能会被误解为 沉默 我正在尝试让logstash运行 所以我按照官方网站上的说明进行独立安装 http logstash net doc
  • 为什么 NSURLSession uploadTaskWithRequest:fromData: 无法上传到 php 服务器?

    php 代码工作正常 我已经从同一服务器上的 html 表单上传了文件 上传的文件大小从 40K 到 2 0M 不等 因此其大小不高 在运行 PHP 5 3 的服务器上激活文件上传 我发现了很多这样的帖子 还没有答案 https stack
  • 绑定到 ViewModel 和 CodeBehind 中的属性

    我确信这是一个可笑的无知问题 但无论如何我还是要问这个问题 因为我搜索了又搜索 要么不理解我所看到的解决方案 要么没有找到我所寻求的答案 我有一个 MVVM 应用程序 我的 XAML 设置为 VM 的 DataContext 其中屏幕上的数
  • 将表部署到表存储中的最佳方法

    你能让我知道吗 进行表存储部署的最佳方法是什么 因为我的开发团队询问他们有很多表 每个表都有数千个条目 因此 他们要求我咨询任何微软团队或博客人们检查进行表存储部署的最佳方法 您知道我们该怎么做吗 因为脚本每次都会耗尽和插入数千个条目 我们
  • Windows 7 上的 VirtualBox 端口转发不起作用

    Windows 7 上的 VirtualBox 端口转发不起作用 我尝试通过端口转发从我的 Windows 7 主机 ssh 到我的 VirtualBox 但 VirtualBox 不会打开端口进行侦听 我可以通过打开 VirtualBox
  • 如何在 Cocoa 中检查文件是否被锁定?

    有没有API可以检查文件是否被锁定 我在中找不到任何 APINSFileManagerclass 让我知道是否有任何API可以检查文件的锁定 我发现以下与文件锁定相关的链接 http lists apple com archives coc
  • 使用 MVC 和 DAO 模式在 JSP 页面中的 HTML 中显示 JDBC 结果集

    我正在使用 JSP 和 JDBC 实现 MVC 我已将数据库类文件导入到 JSP 文件中 并且想显示数据库表的数据 我不知道该如何归还ResultSet从 Java 类到 JSP 页面并将其嵌入到 HTML 中 我怎样才能实现这个目标 在设
  • 从命令行安装 Oracle 客户端,无需用户交互

    我正在寻找一种在 Windows 上安装 Oracle 客户端但从命令行运行的方法 为了自动运行它应有没有用户交互 对于 Oracle Universal Installer 的命令行选项 Oracle 文档非常稀疏 即使运行设置为setu
  • Golang 结构继承没有按预期工作?

    查看这个沙箱 https play golang org p elIHgHAZjT 声明从不同结构继承的结构时 type Base struct a string b string type Something struct Base c
  • 可以在没有 dynamoDB 的情况下使用 AWS App-Sync

    我对 Amazon app sync 的离线和同步功能感兴趣 但我想知道它是否可以在没有 dynamoDB 作为后端的情况下使用 用 VTL 为 dynamoDB 编写的 graphQL 解析器看起来很糟糕 看来使用 mongo 后端会好得
  • 是否可以在越狱的ios上使用外部键盘模拟触摸事件?

    是否可以在 iOS 越狱以及越狱涉及的所有元素上模拟特定屏幕坐标中的触摸事件 按下物理外部键盘 通过相机连接套件或蓝牙的 USB 上的特定按键 我会用它来用脚按下应用程序 振幅 中的按钮 我想使用键盘作为脚踏开关 仅供私人使用 没有应用商店
  • 如何使用 OData 在单个 POST 请求中正确创建和链接一对一关系

    在 OData Operations 文档的第 2 4 节第四段中 它写道 在使用 POST 创建实体时 也可以在同一请求中创建链接 但是 我在尝试完成这项工作时遇到了麻烦 在创建时就多对多链接提出了类似的问题 看起来如果没有批量请求 就不
  • 将 CVC 传递给 stripe.createPaymentMethod JS?

    我需要 CVC 和 Expiry 的单独输入 因此我创建了 3 个 Stripe 元素 let elements stripe elements let cardNumber elements create cardNumber cardN
  • 如何使用窗口函数优化SQL查询

    这个问题与this https stackoverflow com questions 32222889 how to calculate power consumption from power records 一 我有一个包含设备功率值
  • 在 LG WebOS 电视上启用开发者模式

    我正在 LG webOS 智能电视上开发一个简单的应用程序 由于我没能从 USB 驱动器运行我的应用程序 因此我尝试使用 Eclipse IDE 中的开发人员模式 事情是 我添加了一个新的目标配置 指向物理电视 IP 当我尝试连接时 需要密
  • 独特的柱组合

    这是我的简化数据集 foo lt data frame var1 c 1 10 var2 rep 1 5 2 var3 rep 1 2 5 var4 rep 3 7 2 总共 20 个变量 foo var1 var2 var3 var4 v
  • Saml 无 Cookie 保留状态 ASP.NET CORE

    var certbase env IsDevelopment AppDomain CurrentDomain BaseDirectory var pathpfx Path Combine certbase xxxxx pfx var pat
  • 在 Hudson 通知的电子邮件中提供最新测试结果信息

    我有一个项目 有很多测试失败 所以如果我能通过电子邮件收到最新版本的失败测试数量比较 那就太好了 我需要的只是测试结果链接显示在项目页面中的信息 最新测试结果 10 次失败 2 这可能吗 我已经尝试过 email ext 插件 但它并没有告
  • 允许对对象重新排序的算法,同时只需要更新恒定数量的对象位置

    我有一大堆对象 我希望根据它们的一个属性来保持顺序 作为一个例子 我们假设一个对象可能看起来像 var myObject id c 1 position 0 有序集合的简单实现如下所示 id c 1 position 0 id c 2 po