【问题标题】:Sorting a dictionary by key and converting it into an array按键排序字典并将其转换为数组
【发布时间】:2018-02-11 20:04:34
【问题描述】:

我有一本价格和数量的字典。我在一秒钟内多次获得价格和价值的更新,所以我不想将它们存储在数组中,因为字典要快得多。

let mainPriceValDict = [Double:Double]()

数据以 JSON 数组的形式传入,因此我使用可编码来解析 JSON 并将其放入字典中。当我使用数据时,它需要按升序和/或降序排序,因为我正在遍历每个价格以达到一定的总量。我循环的数组格式如下:

let loopingArray = [PriceQuantityEntry]()

struct PriceQuantityEntry {
    let price : Double
    let size : Double
}

我想对作为上述字典中键的价格进行排序,并将它们转换为 PriceQuantityEntry 数组。做这个的最好方式是什么?在升序和决定顺序。我尝试首先对所有键进行排序,然后获取关联值并将它们按顺序放入数组中,但这似乎比此任务实际需要的处理更多。

我认为最好的方法是在结构中放置一个自定义初始化程序,以将字典值转换为 PriceQuantityEntry 类型的值,但我不确定这将如何处理排序。

这就是我目前正在做的工作。我只是觉得有一种更有效的方法可以完成。如果您觉得我应该将结构保留为数组而不是将其转换为字典,请告诉我。

loopingArray = self.mainPriceValDict.sorted { $0.0 < $1.0 }.map { PriceQuantityEntry(price: $0.0, size: $0.1) }

【问题讨论】:

  • 不要对抗框架。如果您需要特定订单,请使用数组。排序键和移动值会导致您失去速度优势。
  • 我使用字典的原因是因为我接收值的频率明显高于我需要使用排序数组的频率。我每秒将收到大约 20-30 次 mainPriceValDict 更新,但我只会每秒将这些值转换为数组 2-3 次。你还认为使用数组有意义吗?
  • 我只接收来自套接字的价格更新,所以如果我使用数组,我首先需要找到该数组中的位置来放置新值,然后将数组附加到该值。您认为使用数组还是字典更有意义?
  • 似乎是 x-y 问题。不要猜测。使用仪器,看看什么是最快的。通过使用二进制搜索将对象插入保持排序的数组中可以非常有效,并且还有其他数据结构(例如树)甚至更快。在这里使用字典以及问题的整个前提可能是完全错误的。
  • 我是这些数据结构的新手。你推荐我学习和使用哪一个?由于 swift 中没有对二进制搜索的本机支持,您是否推荐我使用任何 swift 库?

标签: arrays json swift sorting dictionary


【解决方案1】:

如果您对单个条目进行大量更新,则字典和数组都可能在每次更改条目时都会导致整个内存结构的内存副本。

我建议使用对象(类)而不是结构。这将允许您同时使用数组和字典来引用对象实例。字典将提供对更新的直接访问,而数组将允许以向前或向后的顺序进行顺序处理。

[编辑] 示例:

class PriceQuantityEntry 
{
    static var all:[PriceQuantityEntry] = []
    static var prices:[Double:PriceQuantityEntry] = [:]

    var price : Double
    var size  : Double

    init(price:Double, size:Double)
    {
       self.price = price
       self.size  = size
       PriceQuantityEntry.all.append(self)
       // PriceQuantityEntry.all.resort() // on demand or when new prices added
       PriceQuantityEntry.prices[price] = self
    }

    class func update(price:Double, with size:Double)
    {
       if let instance = PriceQuantityEntry.prices[price]
       { instance.size = size }
       else
       { 
         let _ = PriceQuantityEntry(price:price, size:size) 
         PriceQuantityEntry.resort()
       }
    }

    class func resort()
    {
       PriceQuantityEntry.all.sort{$0.price < $1.price}
    }        
}    

// if adding multiple initial entries before updates ...
let _ = PriceQuantityEntry(price:1, size:3)
let _ = PriceQuantityEntry(price:1.25, size:2)
let _ = PriceQuantityEntry(price:0.95, size:1)
PriceQuantityEntry.resort()

// for updates ...
PriceQuantityEntry.update(price:1, with: 2)

// going throug list ...
var count:Double = 0
var total:Double = 0
var quantity:Double = 5
for entry in PriceQuantityEntry.all
{
  total += min(entry.size,quantity-count) * entry.price
  count = min(quantity,count + entry.size)
  if count == quantity {break}
}

【讨论】:

  • 你能举个例子说明你会如何推荐我这样做吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
  • 2020-08-24
  • 1970-01-01
  • 2021-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多