Choosing the Correct Container

Oct 21, 2012 at 3:00pm
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 Oct 21, 2012 at 3:01pm
Oct 21, 2012 at 4:27pm
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.
Oct 21, 2012 at 4:56pm
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 Oct 21, 2012 at 5:37pm
Oct 21, 2012 at 6:42pm
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.