【问题标题】:Efficient [JS?] algorithm to list and update multiple location buy/sell prices高效的 [JS?] 算法列出和更新多个位置的买入/卖出价格
【发布时间】:2018-03-09 20:59:28
【问题描述】:

不,这不是面试问题,也不是加密货币! :)
它是一个个人的非营利网络应用程序来补充游戏。

这个问题部分是财务,部分是代码。
我正在用 Vue 编写这个 web 应用程序,所以我更喜欢 JavaScript 解决方案,但抽象的方法很好,伪代码会很棒,而且我应该能够将任何 impl 转换为 JavaScript。

场景是这样的:
多个地点(例如:“商店”)以不同的价格买卖多种商品。
价格随机变化(可能是由于供求关系,但这无关紧要)。
将有 100-1000 个位置和 10-100 个项目。
大多数地点(估计 80-90%)只会购买/出售少数商品。
一些地点(估计 1-10%)将购买/出售许多或所有商品。
一些地点(估计为 50%)可能只买不卖,或者只卖不买。

我想向所有具有该物品售价的位置(类似于排列/组合,但有许多预期的差距)显示具有物品购买价格的所有位置的详尽列表。
最终渲染的数据必须只是一个简单的对象列表/数组(键控/值)。

99M 个对象的分页列表(1000 个商店 * (1000 - 1) 个商店 * 100 个项目)是最坏的情况,但预计数据中会有 很多 空白,所以希望有远少于 1M 个对象(我希望不超过 100,000 个;这些不必都存在于内存中;我可以选择从存储中加载它们)。

示例(按商品和购买位置排序以更好地查看示例数据集):
Item Buy Location Buy Price Ratio Sell Price Sell Location Item A Location A 4 0.5 2 Location B Item A Location A 4 2.0 8 Location C Item A Location B 6 0.66 4 Location A Item A Location B 6 1.33 8 Location C Item A Location C 10 0.4 4 Location A Item A Location C 10 0.2 2 Location B Item B Location A 3 0.33 1 Location B Item B Location A 3 1.33 4 Location C Item B Location B 3 0.66 2 Location A Item B Location B 3 1.33 4 Location C Item B Location C 5 0.4 2 Location A Item B Location C 5 0.2 1 Location B

列表中的每一列都是可排序的;默认排序将是“比率”,它将显示买卖地点的最佳组合。 当任何价格更新时,Vue 会自动更新列表并重新排序。

现在,我对如何做到这一点有了自己的想法,但它的效率非常低,因为我的解决方案是在任何单个价格发生变化时重新生成整个列表。
由于最终输出需要是一个可以任意排序的列表,因此没有真正的方法来索引或直接访问这些项目。
如果位置 C 的 Item A Buy Price 的价格发生变化,就没有办法说“更新 X 行 Y 列”,甚至只是“更新 X 行”。

但是,我怀疑我错过了什么。
我想这是一项相当普遍的任务,之前已经以可扩展的方式实施过。
示例:跨多个交易所的“简单”买入/卖出价格图表。
我曾考虑过查看开放的 Crypto[Bot] 代码,但这似乎更像是我想要理解的“财务”问题,而不是我想要复制的编码问题。

您将如何实现这一点?
您会使用哪种数据集?

谢谢!

【问题讨论】:

  • 这对我来说似乎离题了,因为它非常广泛,它不是一个特定的编程问题。如果列表是一个位置的所有项目,或者一个项目的所有位置,或者最高或最低 n 比率,那么回答会容易得多。否则你会得到你的 n*(n-1)*y 比率列表。

标签: javascript vue.js vuetify.js


【解决方案1】:

在我看来

  • 1M 行数据太多,用户一次读不完。
  • 1M 的数组大小对于 javascript 来说并不算大(大约 10MB,您可以在您的应用程序中检查 see how),但是将其全部渲染到 DOM 元素可能是一个非常大的问题。

你将如何实现它?

所以在这种情况下,我将使用分页或聚合(例如,每个项目的前 10 个最高比率)。

例子:

computed: {
  displayItems () {
    // This will update when one of rawItems, currentPage, pageSize updated
    return doFilterOrSort(rawItems).slice(currentPage * pageSize, pageSize)
  }
}

这将解决DOM元素过多的问题(如上我假设更新1M数组大小足够快,不会成为瓶颈)。

如果您的数据变化非常频繁,例如每秒 10 次。您可以通过节流或去抖动来减少渲染时间来改善这一点。

节流示例:

watch: {
  rawItems () {
    if (!ticking) {
      requestAnimationFrame(() => {
        displayItems = doFilterOrSort(rawItems).slice(currentPage * pageSize, pageSize)
        ticking = false
      })
      ticking = true
    }
  }
}

如果您想要无限滚动等行为,您可以通过回收已经超出屏幕的 DOM 元素来实现。请参阅react-virtualized 中的示例。

你会使用什么样的数据集?

您没有说明您检索到的数据格式(初始和每次更新;按商店?按商品?)所以很难回答。

我假设商店和商品的数量是固定的(不经常更新),并且每次更新都是针对商店中的商品。用 nm 表示商店和商品的数量。

我将使用 3 个数组:

第一个数组,用于保留每个商店中每个商品的购买/出售价值。您可以在 O(1) 中轻松更新它。

第二个数组,用于保持每个项目的每个存储组合的比率对象,例如:

[
  [aa, ab, ac],
  [ba, bb, bc],
  [ca, cb, cc]
]

// 3 stores, 1 item, each element is { r, a, b }
// r for ratio, a buy store, b sell store

您可以使用 O(n⋅n) 来更新它,例如更新 a:循环 1 到 n,对于 i = 2 更新 abba

第三个数组用于保持与先前相同的对象加上讨人喜欢或分组。进行排序或分组将花费 O((n⋅n⋅m) log (n⋅n⋅m)) (是的,这是您需要注意的瓶颈,方法取决于你的数组形状)。

在更大的范围内(或以上所有都没有帮助,抱歉)我认为与其将所有数据发送到客户端,不如将其聚合在服务器中,然后通过 Web 套接字发送。

【讨论】:

  • 谢谢!我将根据我在其他地方收到的反馈和其他反馈来调整我的 codepen。一旦codepen稳定,如果您的回答有帮助,我很乐意接受! :)
猜你喜欢
  • 1970-01-01
  • 2015-07-24
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
  • 2010-12-12
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
相关资源
最近更新 更多