根据对值对多维映射进行排序

Sort multidimensional map based on pair value

本文关键字:映射 排序      更新时间:2023-10-16

我有一个定义如下的映射:

std::map<std::string, std::vector<std::pair<std::string, std::string>>> groupList;

目标:
我有一组命令的列表。我想按顺序排列每组。为了做到这一点,每个组都有一个"序列"值。我想根据这个值从最小到最大对整个列表进行排序。从本质上讲,我有一个元素列表,每个元素都有一个附带的列表,其中列出了每个父元素特有的其他值。我想按子列表中的特定对或值对父列表进行排序。

为了将其可视化,我用PHP创建了一个具有类似结构的数组。我不知道如何将C++映射可视化,所以这只是我的假设。1、2、3是地图的关键点。

Array
(
    [1] => Array
        (
            [groupID] => 1
            [sequence] => 0
            [command] => DefaultState
        )
    [2] => Array
        (
            [groupID] => 2
            [sequence] => 2
            [command] => Restart
        )
    [3] => Array
        (
            [groupID] => 3
            [sequence] => 1
            [command] => Beep
        )
)

我想根据里面一个特定对的值对这个映射进行排序,在这种情况下是"序列"。使用"sequence"值排序时,元素"2"应位于元素"3"之下最终结果如下:

Array
(
    [1] => Array
        (
            [groupID] => 1
            [sequence] => 0
            [command] => DefaultState
        )
    [3] => Array
        (
            [groupID] => 3
            [sequence] => 1
            [command] => Beep
        )
    [2] => Array
        (
            [groupID] => 2
            [sequence] => 2
            [command] => Restart
        )
)

很抱歉在这里混合了语言,但对于我来说,没有简单的方法来转储描述其结构的地图(据我所知)。起初,我的地图是这样设置的:

std::map<std::string, std::map<std::string, std::string>> groupList;

这对我来说更容易添加元素,然后再访问它们,但我认为向量对更容易用于排序。为了方便起见,我更愿意使用后一个定义。我曾考虑过使用std::sortboost,但在实现这个特定案例时运气不佳。

欢迎任何意见/帮助。谢谢

每当我看到一个数据结构时,我都会想到一个方便的定义:

struct Item {
    int groupID;
    int sequence;
    std::string command;
}

现在,您可以简单地定义数组:

Item arr[] = {
    { 1, 0, "DefaultState" },
    { 2, 2, "Restart"      },
    { 3, 1, "Beep"         },
};

由于它是一个具有值语义的简单聚合,您可以定义一个顺序并对其进行排序:

struct Item {
    int groupID;
    int sequence;
    std::string command;
    bool operator<(Item const& other) const {
         return sequence < other.sequence;
    }
};

Demo

添加流媒体运营商<lt;我们得到了一个完整的工作演示:

在Coliru上直播

#include <iostream>
struct Item {
    int groupID;
    int sequence;
    std::string command;
    bool operator<(Item const& other) const {
        return sequence < other.sequence;
    }
    friend std::ostream& operator<<(std::ostream& os, Item const& i) {
        return os << "Item { group:" << i.groupID << ", sequence:" << i.sequence << ", command:'" << i.command << "' }";
    }
};
#include <algorithm>
int main() {
    Item arr[] = {
        { 1, 0, "DefaultState" },
        { 2, 2, "Restart"      },
        { 3, 1, "Beep"         },
    };
    std::sort(std::begin(arr), std::end(arr));
    for (auto& item : arr)
        std::cout << item << 'n';
}

打印

Item { group:1, sequence:0, command:'DefaultState' }
Item { group:3, sequence:1, command:'Beep' }
Item { group:2, sequence:2, command:'Restart' }

扩展我之前的回答,如果你真的在寻找更高级的东西,下面是使用Boost MultiIndex容器时想到的:

在Coliru上直播

#include <fstream>
#include <iostream>
struct Item {
    int groupID;
    int sequence;
    std::string command;
    friend std::ostream& operator<<(std::ostream& os, Item const& i) {
        return os << "Item { group:" << i.groupID << ", sequence:" << i.sequence << ", command:'" << i.command << "' }";
    }
};
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
namespace bmi = boost::multi_index;
using Table = bmi::multi_index_container<
        Item,
        bmi::indexed_by<
            bmi::ordered_unique<
                bmi::tag<struct by_group>,
                bmi::member<Item, int, &Item::groupID>
            >,
            bmi::ordered_unique<
                bmi::tag<struct by_sequence>,
                bmi::member<Item, int, &Item::sequence>
            >
        >
    >;
#include <algorithm>
#include <map>
int main() {
    Table arr = {
        { 1, 0, "DefaultState" },
        { 2, 2, "Restart"      },
        { 3, 1, "Beep"         },
    };
    for (auto& item : arr.get<by_group>())
        std::cout << item << 'n';
    std::cout << "nsorted by sequence:n";
    for (auto& item : arr.get<by_sequence>())
        std::cout << item << 'n';
}

打印

Item { group:1, sequence:0, command:'DefaultState' }
Item { group:2, sequence:2, command:'Restart' }
Item { group:3, sequence:1, command:'Beep' }
sorted by sequence:
Item { group:1, sequence:0, command:'DefaultState' }
Item { group:3, sequence:1, command:'Beep' }
Item { group:2, sequence:2, command:'Restart' }