Picking array items by name

Started by
6 comments, last by Luctus 21 years, 12 months ago
One could think I''ve been programming long enough to know an answer of this but... Anyway I''ve got an array like this: MyType MyArray[10]; And then I pick one of the items: MyArray[3].DoSomething(SomeArgument); Now, for the simplicity of things, I want to be able to give each item in the array a name and then use that name as identifier. Something like this: MyType MyArray[10]; MyArray[0].Name = "Item1" MyArray[1].Name = "AnotherItem" MyArray[2].Name = "AThidItem" ..and so on.. MyArray[AnotherItem].DoSomething(SomeArgument); The point is, that I want to be able to assign a name dynamicly. I know it would have been easy using defines or an enum. Suggestions? -Luctus
-LuctusIn the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move - Douglas Adams
Advertisement
Your assigning names as strings, so you would want to be able to get the object based on that (string name), no?


I don''t think you can do this w/ a normal array.. this is not perl (in which I''m pretty sure you can).

You''ll have to create an class that mimics an array, and probably create it as a template. And allow the passing of a string as an argument to operator []. Then use the name to search for the object in the array.. Just a suggestion.

Otherwise, you could do enums, but I don''t think you can create new enum values at run time.

Sorry if this didn''t help.
std::map is what you''re looking for.


  #include <map>#include <string>using namespace std;map<string, MyType> MyMap;// to insert a memberMyType SomeType;MyMap.insert( make_pair( "Item1", SomeType ) );// to look it up the easy wayMyType AnotherType = MyMap["Item1"];// for a faster looking up (i think)map<string, MyType>::iterator it = MyMap.find("Item1");if (it == MyMap.end()) {  // "Item1" wasnt found} else {  // else "Item1" was found  MyType YetAnotherType = (*it).second;}  


This is all from memory so i could be wrong, but it should work.
--------------------Go Stick Your Head In A Pig
The closest thing to what you want is a map or other associative data structure. What a map does is that it keeps sorted pairs of keys and values (the STL std::map allows only one value per key; std::multimap allows multiple values per key):
#include <map>std::map< std::string, long > Items;...Items[ "You" ] = 0;Items[ "Me" ] = 1;...cout << ( Items[ "Him" ] = 2 ) << endl; 


[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! | Asking Smart Questions | Internet Acronyms ]
Thanks to Kylotan for the idea!
I see three ways to solve your problem:

- The first easy way would be to make a fuction that searches through your class array:
MyType* GetObject(char* Object_Name)
...i=0
...while (i < max_number of objects)
......if (strcomp(MyArray.Name, Object_Name) == 0)
.........return MyArray<br>……i++<br><br>It is not reusable. You can create a class manager that holds a pointer to the array and that implements different methods to search or modify your array. A little better design wise, but you are then closer to …<br><br>- The second way is to create a vector of your class and use the find algorithm (STL)<br>If you are not proficient with vectors and algorithms, look at the following links: <br>www.sgi.com/tech/stl/<br>www.devx.com/upload/free/features/vcdj/2000/04apr00/bw0400/bw0400.asp<br><br>- The third way is to create your own templated array manager. See the following link to get you started more generally on templates:<br>http://www.infosys.tuwien.ac.at/Research/Component/tutorial/prwmain.htm<br><br>Hope that helps.<br><br>Ghostly yours,<br>Red. </i>
Ghostly yours,Red.
Red:
[ source ]
[ /source ]
(without spaces) will put your code in nice little source blocks. Just FYI. Also takes care of problem of italicizing your entire post if you use ''i'' in a subscript. Good posts, btw. Good to have you around.
Just to extend what Red Ghost already said, you could make yourself a simple array class and overload operator[] to accept string literals instead of a numeric index. You could do something like this:

  template<class T>class array{    private:        template<class T>        struct node        {            T data;            const char* name;        };    public:        array(unsigned int initial_capacity = 0):            m_capacity(initial_capacity), m_size(0), m_data(0)            {reserve(initial_capacity);}        ~array()            {clear();}        unsigned int size() const {return m_size;}        unsigned int capacity() const {return m_capacity;}        void reserve(unsigned int new_capacity)        {            if(new_capacity <= m_capacity)                return;            node<T>* temp = new node<T>[new_capacity];            for(unsigned int = 0; i < m_capacity; ++i)                temp[i] = m_data[i];            delete m_data;            m_data = temp;            m_capacity = new_capacity;        }        void add(const char* name, const T& data)        {            reserve(++m_size);            m_data[m_size+ 1] = data;        }        void clear()        {            delete[] m_data;            m_size = m_capacity = 0;        }        T& operator[](const char* name)        {            for(unsigned int i = 0; i < m_size; ++i)                if(strcmp(m_data[i].name, name) == 0)                    return m_data[i].data;            // to keep the compiler happy (we should throw            // an exception before we get here)            return m_data[0].data;        }        const T& operator[](const char* name) const        {            for(unsigned int i = 0; i < m_size; ++i)                if(strcmp(m_data[i].name, name) == 0)                    return m_data[i].data;            // to keep the compiler happy (we should throw            // an exception before we get here)            return m_data[0].data;        }    private:        node<T>* m_data;        unsigned int m_capacity;        unsigned int m_size;};  


What can I say? I felt like coding. With this code—assuming that it''s correct—you should be able to do std::vector-like stuff, but using a string literal for access.


  array<int> stuff(4); // reserve enough space for 4 items, though                     // both add and reserve can increase thisstuff.add("Peach", 3);stuff.add("Banana", 1);stuff.add("Orange", 5);stuff.add("Apple", 6);stuff["Orange"] = 6;if(stuff["Apple"] == stuff["Orange"])    stuff["Peach"] = 2;  
Well, thanks for all your help, I''ll see what I can do with it.

-Luctus
-LuctusIn the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move - Douglas Adams

This topic is closed to new replies.

Advertisement