Boost :: Multi_Index运行总计

问题描述 投票:0回答:1

首先,对格式不佳表示抱歉,我是新手,知道我做的还不够漂亮。

我正在实施一个系统来跟踪我存储为块的订单,并且我还没有模板的经验来完全理解参考文档。 (我尽力阅读了这篇文章,并获得了对Joaquin的广泛尊重。似乎没有示例显示带有排序的复合键)

struct Block{//Variable types apart from the bool are immutable, values may be modified though
/*  
This is to replace the previous lookup structure consisting of a map of buys and sells, to a map of products, to a map of prices, to a map of priorities, pointing to a struct holding the blockID and quantity

For a modify, if they are changing products or prices, it will create a new order, else they can shrink quantity desired without changing the priorityAtPrice
If they want to increase the quantity they lose their priority, but the order will keep the other values
*/
    const int32_t productID; //One of ~20 different products 
    mutable uint32_t orderQuantity;//Number of products wanted at that price
    const int64_t desiredPrice; //Prices are not unique
    mutable uint64_t priorityAtPrice;//It's a global priority, in case someone alters their order
    const uint64_t blockID;//Unique to every block
    bool buy;//Tag to note if they are a looking to sell or buy

    bool operator<(const Block& lilBlock)const{return blockID<lilBlock.blockID>}

};
struct idHash{
    uint64_t operator()(const Block& lilBlock)const{
        return lilBlock.blockID;
    }
}
struct ObtainElementByBlockID {};
struct ObtainSublistByProductAndPrice {};
struct PlaceInLine {};
struct randomAccess {};

typedef boost::multi_index_container<
Block*,//Data type being stored, in this case, it is a pointer to Block.
//I'd like to store the block objects in an array[size uint64_t] indexed by the BlockIDs, since they are unique and will be accessed often, so keeping as much in cache is desirable
boost::multi_index::indexed_by<
    boost::multi_index::hashed_unique<//Ideally should be fed an ID and retrieve the orderBlock in O(1) time
    //It is never needed to compare IDs beyond checking if that is the ID being queried for
        boost::multi_index::tag<ObtainElementByBlockID>
        ,boost::multi_index::member<Block,uint64_t, blockID>
        ,idHash
    >
    ,boost::multi_index::random_access<
        boost::multi_index::tag<randomAccess>
        ,boost::multi_index::member<Block,uint64_t,blockID>
    >   
    ,boost::multi_index::ordered_non_unique<//Should return a sublist at a product/price pair ordered by priorityAtPrice
        boost::multi_index::tag<ObtainSublistByProductAndPrice>
        ,boost::multi_index::composite_key<
            Block,
            boost::multi_index::member<Block, int32_t, &Block::productID>
            ,boost::multi_index::member<Block, int64_t, &Block::desiredPrice>
            ,boost::multi_index::member<Block, uint64_t, &Block::priorityAtPrice>
        >
        ,boost::multi_index::composite_key_compare<
            std::equal<int32_t>
            ,std::equal<uint64_t>
            ,std::less<uint64_t>
        >
    >
    /*
    I think what I want has to do with rank
    At product/price/buy, the value returned should be the sum of the quantities with a lower priority. 

    Say at   [chairs, 5$, buy=true]   there are orders(priority,quantity)
    such that {(2,5),(6,12),(896, 3)}
    with block IDs {753, 54, 712}
    Querying for the place in line of a block, given the blockID 712
    It should return 17, since there are orders ahead of block 712 with quantities 5+12=17
    (It might actually need to return 18, but that's trivial)
    */
    ,boost::multi_index::ranked_non_unique<
        boost::multi_index::tag<PlaceInLine>
        ,boost::multi_index::composite_key<
            Block,
            boost::multi_index::member<Block, int32_t, &Block::productID>
            ,boost::multi_index::member<Block, int64_t, &Block::desiredPrice>
            ,boost::multi_index::member<Block,priorityAtPrice>
        >
        ,boost::multi_index::composite_key_compare<
            std::equal<int32_t>
            ,std::equal<uint64_t>
            ,std::less<uint64_t>
        >
    >

> BlockDatabase;

我需要确保我的multi_index格式正确的帮助。

P.S。 -能够快速从给定的产品/价格中提取购买或出售的总金额的任何帮助将不胜感激。

c++ boost multi-index latency boost-multi-index
1个回答
0
投票

您的帖子没有提供MCVE,并且其中的代码确实存在许多错误,即使添加了所需的额外代码(标头和内容),它们也无法编译。

因此,我重新编写了修复在执行过程中发现的错误的程序,您可以在下面找到结果。关于您的主要问题,您不需要为此的排名索引,有序索引就足够了。您想要的是orderQuantity,具有相同productIDdesiredPrice和买/卖标记且比给定块低的priorityAtPrice的块的productID总数:您需要一个索引,该索引按([[ C0],desiredPricebuypriorityAtPrice):

boost::multi_index::ordered_non_unique<
    boost::multi_index::tag<ObtainSublistByProductPriceAndBuy>
    ,boost::multi_index::composite_key<
        Block,
        boost::multi_index::member<Block, const int32_t, &Block::productID>
        ,boost::multi_index::member<Block, const int64_t, &Block::desiredPrice>
        ,boost::multi_index::member<Block, bool, &Block::buy>
        ,boost::multi_index::member<Block, const uint64_t, &Block::priorityAtPrice>
    >
>

和一个检索适当范围并求和的函数:

uint32_t placeInLine(const BlockDatabase& bd, const Block& b)
{
    auto& index = bd.get<ObtainSublistByProductPriceAndBuy>();
    auto  first = index.lower_bound(
        std::make_tuple(b.productID, b.desiredPrice, b.buy));
    auto  last  = index.lower_bound(
        std::make_tuple(b.productID, b.desiredPrice, b.buy, b.priorityAtPrice));
    return std::accumulate(
      first, last, uint32_t(0),
      [](uint32_t n, const Block* pb){ return n + pb->orderQuantity; });
}

下面是完整示例。

[Live On Coliru] >>

#include <array>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <iostream>
#include <numeric>

struct Block{

    const int32_t productID;
    mutable uint32_t orderQuantity;
    const int64_t desiredPrice;
    mutable uint64_t priorityAtPrice;
    const uint64_t blockID;
    bool buy;

    bool operator<(const Block& lilBlock)const{return blockID<lilBlock.blockID;}
};

struct ObtainElementByBlockID {};
struct RandomAccess {};
struct ObtainSublistByProductAndPrice {};
struct ObtainSublistByProductPriceAndBuy {};

typedef boost::multi_index_container<
Block*,
boost::multi_index::indexed_by<
    boost::multi_index::hashed_unique<
        boost::multi_index::tag<ObtainElementByBlockID>
        ,boost::multi_index::member<Block,const uint64_t,&Block::blockID>
    >
    ,boost::multi_index::random_access<
        boost::multi_index::tag<RandomAccess>
    >   
    ,boost::multi_index::ordered_non_unique<
        boost::multi_index::tag<ObtainSublistByProductAndPrice>
        ,boost::multi_index::composite_key<
            Block,
            boost::multi_index::member<Block, const int32_t, &Block::productID>
            ,boost::multi_index::member<Block, const int64_t, &Block::desiredPrice>
            ,boost::multi_index::member<Block, const uint64_t, &Block::priorityAtPrice>
        >
    >
    ,boost::multi_index::ordered_non_unique<
        boost::multi_index::tag<ObtainSublistByProductPriceAndBuy>
        ,boost::multi_index::composite_key<
            Block,
            boost::multi_index::member<Block, const int32_t, &Block::productID>
            ,boost::multi_index::member<Block, const int64_t, &Block::desiredPrice>
            ,boost::multi_index::member<Block, bool, &Block::buy>
            ,boost::multi_index::member<Block, const uint64_t, &Block::priorityAtPrice>
        >
    >
>
> BlockDatabase;

uint32_t placeInLine(const BlockDatabase& bd, const Block& b)
{
    auto& index = bd.get<ObtainSublistByProductPriceAndBuy>();
    auto  first = index.lower_bound(
        std::make_tuple(b.productID, b.desiredPrice, b.buy));
    auto  last  = index.lower_bound(
        std::make_tuple(b.productID, b.desiredPrice, b.buy, b.priorityAtPrice));
    return std::accumulate(
      first, last, uint32_t(0),
      [](uint32_t n, const Block* pb){ return n + pb->orderQuantity; });
}

int main()
{
    const int32_t chairsID = 0;

    auto blocks = std::array{
      Block{chairsID,  5, 5,   2, 753, true},
      Block{chairsID, 12, 5,   6,  54, true},
      Block{chairsID,  3, 5, 896, 712, true}
    };

    BlockDatabase bd;
    for(auto& b: blocks) bd.insert(&b);

    // retrieve block with blockID 712
    auto it = bd.find(712);

    // output sum of quantities for blocks with same productID, desiredPrice
    // and buy tag and lower priorityAtPrice
    std::cout << placeInLine(bd, **it) << "\n";
}

输出

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