Choosing the Correct Container

I have a data structure that contains several different types of data like so:

1
2
3
4
5
6
7
8
9
struct Tool
{
    const int        toolID;
    const QString    toolName;
    const QString    categoryName;
    int              outcomeID;
}

typedef boost::shared_ptr<Tool> ToolPtr;


I'm struggling to decide what container to use for the job.

I originally settled on std::vector, following this guide at the bottom of the page
http://linuxsoftware.co.nz/cppcontainers.html
because my data set is small (no more than 40 Tools), and because no tools will be removed or added.

Through many points of the application the tools need to be accessed by different means, and I find myself written way too many loops and using std::find/lower_bound/upper_bound all over the place.

The tools are retrieved from a database at program startup.

About 50% of the time they need to be grouped together by outcomeID and shown in a table.

About 25% of the time they are grouped by categoryName in a tree structure,
where the category will contain only the tools with that categoryName AND as long as they have a particular outcome Id.

As the program grows I'm seeing that I also need to access get the tools by the toolID frequently as well.

I'm trying to figure out what container is best for all of these cases, or if perhaps I should re-arrange the data structure.
Last edited on
How about wrapping your set of Tools in a class ToolSet?

The class provides methods for the various types of access. A vector inside should be fine.

The main problem is writing repeated bits of code rather than any performance issues related to the container type and relative frequencies of different types of access.
So something kind of like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class ToolSet
{
public:

    typedef std::vector< ToolPtr > ToolVector;

    ToolVector allTools()
    {
        return mToolVec;
    }

    ToolVector toolsByOutcome(const int outcomeID)
    {
        ToolVector toolVec;

        ToolVector::iterator mid;

        mid = std::stable_partition(
            mToolVec.begin(),
            mToolVec.end(),
            [&outcomeID](const ToolPtr &a) -> bool
            {
                return (a->outcomeID == outcomeID);
            });

        toolVec.assign(mToolVec.begin(), mid);

        return toolVec;
    }

    ToolVector toolsByCategory(const QString &cat)
    {
        ...
    }

    ToolVector toolsByCategory(const QString &cat, const int outcomeID)
    {
        ...
    }

    ToolPtr toolById(const int toolID);

private:

    ToolVector    mToolVec;
};


EDIT: had lamba expression wrong.
Last edited on
Yeah, You could have the various ways of extracting a bunch of tools return a ToolSet.

So ToolSet is the universal "bunch of tools" object and you never need to see ToolVector

And any ToolSet will supply all those services - giving you loads of flexibility
Topic archived. No new replies allowed.