C++ 基于对值的多维映射排序

C++ 基于对值的多维映射排序,c++,sorting,dictionary,boost,vector,C++,Sorting,Dictionary,Boost,Vector,我的地图定义如下: std::map<std::string, std::vector<std::pair<std::string, std::string>>> groupList; 我想根据内部特定对的值对该映射进行排序,在本例中为“序列”。使用“序列”值排序时,元素“2”应位于元素“3”之下最终结果如下所示: Array ( [1] => Array ( [groupID] => 1

我的地图定义如下:

std::map<std::string, std::vector<std::pair<std::string, std::string>>> groupList;
我想根据内部特定对的值对该映射进行排序,在本例中为“序列”。使用“序列”值排序时,元素“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::映射组列表;
这对我来说更容易添加元素,然后稍后访问它们,但我认为向量对更容易用于排序。为了方便起见,我宁愿使用后一种定义。我正在考虑使用
std::sort
boost
,但我没有幸实现这个特定案例


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

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

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;
    }
};

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

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;
    }
};
继续扩展,如果您真的在寻找更高级的东西,下面是使用Boost多索引容器时想到的:

#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';
}
#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';
}
继续扩展,如果您真的在寻找更高级的东西,下面是使用Boost多索引容器时想到的:

#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';
}
#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';
}


这有点令人困惑。。。如果你能说出你真正想要映射到某个数据结构的东西,也许会更清楚。你的代码> STD::MAP<代码>气味超标。考虑C++映射,它是与对象相关的不同键的有序集合。这种顺序是由map声明本身建立的。以后不会“排序”。如果你描述了你想做的事情,而不是仅仅描述你想做的事情,这将非常有帮助。我编辑了一些内容,以更好地展示最终结果,并添加了对我试图完成的事情的解释。我不认为map的顺序可以改变,所以我可能需要以不同的方式实现它。我建议您为这样一个复杂的结构创建一个自己的
struct
class
。如果它确实是某事物的
映射
向量
,则使用
std::
版本,但如果使用
只是为了避免创建自己的类型,那么最好创建它。然后一切都会变得更清楚。它真的有那么复杂的结构吗?这似乎是很多人已经实现的东西,或者类似的东西。这有点让人困惑。。。如果你能说出你真正想要映射到某个数据结构的东西,也许会更清楚。你的代码> STD::MAP<代码>气味超标。考虑C++映射,它是与对象相关的不同键的有序集合。这种顺序是由map声明本身建立的。以后不会“排序”。如果你描述了你想做的事情,而不是仅仅描述你想做的事情,这将非常有帮助。我编辑了一些内容,以更好地展示最终结果,并添加了对我试图完成的事情的解释。我不认为map的顺序可以改变,所以我可能需要以不同的方式实现它。我建议您为这样一个复杂的结构创建一个自己的
struct
class
。如果它确实是某事物的
映射
向量
,则使用
std::
版本,但如果使用
只是为了避免创建自己的类型,那么最好创建它。然后一切都会变得更清楚。它真的有那么复杂的结构吗?这似乎是很多人已经实现的东西,或者类似的东西。非常感谢。但是,我确实希望能够使用groupID访问数据,这就是为什么在我的问题中,我有一个以组ID为键的父元素映射。我想保持一个类似的结构。那么看另一个答案。基本上可以归结为:地图是有序的容器。元素不能同时处于两个顺序(逻辑矛盾)。所以你需要分开收集。自从罗马建立以来,数据库一直在为此使用多个索引。但是,我确实希望能够使用groupID访问数据,这就是为什么在我的问题中,我有一个以组ID为键的父元素映射。我想保持一个类似的结构。那么看另一个答案。基本上可以归结为:地图是有序的容器。元素不能同时处于两个顺序(逻辑矛盾)。所以你需要分开收集。自从罗马建立以来,数据库一直在为此使用多个索引Hanks!例如,如何访问groupID为2的项的“command”元素?当使用映射时,我只需使用[]操作符即可轻松查找数据。就像
项[“2”][“命令”]
一样。你不可能既有蛋糕又吃。但您可以“破解”它,例如使用PropertyMaps:。对于这里的简单项目类型,编译器可以优化成本。注意,尽管语义不同:可以选择插入一个元素,但返回不是通过引用。我个人会制作一个访问器函数,在这里向您隐藏机制,而不是强迫它看起来像一个可变的
std::map
,我想您可能是对的。C++对我来说是新的,结构也有很大的不同。您建议如何创建访问器函数?类似于你发布的coliru链接的东西?我想我需要一些东西来按组ID删除一个元素,添加一个新元素,等等。哇,太好了,非常感谢!唯一让我困惑的是我