Mark
Mark

Reputation: 11

Vector point to another vector

What I have here is two arrays of different types that I'm converting to vectors.

int ham_array[] = {32,71,12,45,26};

char word_array[] = {"cat", "bat", "green", "red", "taxi"};


vector < int > hamvector (ham_array, ham_array + 5);               

vector < char > wordvector(word_array, word_array + 5); 

I am going to call a sort function to sort the elements of ham_array from least to greatest. At the same time, I would like the word_array to also get sorted the same way ham_vector gets sorted using references.

For example,

after I call sort(hamvector)

ham_array[] = {12, 26, 32, 45, 71}

and sort(wordvector)

word_array[] = {"green", "taxi", "cat", "red", "bat"};

Is there an easy way to do this?

Upvotes: 1

Views: 1945

Answers (3)

Sion Sheevok
Sion Sheevok

Reputation: 4217

I've tried to find a solution to a similar problem before and ultimately had to sort it manually. Another way I imagine you could do this would be to write a sorter functor that can somehow figure out, based on which string is being sorted, which integer is associated, and sort based on that. This is terribly inefficient, so I would highly advise doing your own manual sorting using std::swap.

#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

template<typename KeyType, typename ValueType>
class CMappedSorter
{
    std::map<KeyType, ValueType>* const m_Mappings;
public:
    CMappedSorter(std::map<KeyType, ValueType>* Mappings) : m_Mappings(Mappings)
    {

    }

    bool operator()(KeyType& LHS, KeyType& RHS)
    {
        const ValueType LHSSortingValue = m_Mappings->find(LHS)->second;
        const ValueType RHSSortingValue = m_Mappings->find(RHS)->second;
        return (LHSSortingValue < RHSSortingValue);
    }
};

int main(int argc, char* argv[])
{
    std::vector<int> Integers;
    std::vector<std::string> Strings;

    Integers.push_back(3);
    Integers.push_back(1);
    Integers.push_back(2);

    Strings.push_back("Apple");
    Strings.push_back("Banana");
    Strings.push_back("Cherry");

    std::map<std::string, int> Mappings;

    if(Integers.size() == Strings.size())
    {
        const unsigned int ElementCount = Strings.size();

        // Generate mappings.
        auto StringsIterator = Strings.begin();
        auto IntegersIterator = Integers.begin();
        for(unsigned int i = 0; i < ElementCount; ++i)
        {
            Mappings[*(StringsIterator)] = *(IntegersIterator);
            ++StringsIterator;
            ++IntegersIterator;
        }

        // Print out before sorting.
        std::cout << "Before Sorting" << std::endl;
        std::cout << "Int\tString" << std::endl;
        StringsIterator = Strings.begin();
        IntegersIterator = Integers.begin();
        for(unsigned int i = 0; i < ElementCount; ++i)
        {
            std::cout << *(IntegersIterator) << '\t' << *(StringsIterator) << std::endl;
            ++StringsIterator;
            ++IntegersIterator;
        }

        // Sort
        std::sort(Strings.begin(), Strings.end(), CMappedSorter<std::string, int>(&(Mappings)));
        std::sort(Integers.begin(), Integers.end());

        // Print out after sorting.
        std::cout << "After Sorting" << std::endl;
        std::cout << "Int\tString" << std::endl;
        StringsIterator = Strings.begin();
        IntegersIterator = Integers.begin();
        for(unsigned int i = 0; i < ElementCount; ++i)
        {
            std::cout << *(IntegersIterator) << '\t' << *(StringsIterator) << std::endl;
            ++StringsIterator;
            ++IntegersIterator;
        }
    }
    else
    {
        std::cout << "Error: Number of elements in each container are not equivalent." << std::endl;
    }
}

Upvotes: 0

greatwolf
greatwolf

Reputation: 20858

If by simple, you mean a more direct way then yes. The std::sort() does support sorting of raw arrays as well:

sort(word_array, word_array + 5, wordcmp);

As Blindy showed, you need a comparator function to tell sort how the ordering is suppose to be done for your list of words. Otherwise you'll end up sorting by the memory address that the string resides at instead of by the letters in your string. Something like this should work:

int wordcmp(const char *lhs, const char *rhs)
{
    return strncmp(lhs, rhs, 256) < 0;
}

One other note, in practice you'll want to prefer std::vector over just raw pointer arrays since the latter isn't as safe.

Upvotes: 0

Blindy
Blindy

Reputation: 67417

Well for one thing, that would be char *word_array[], the way you declared it would be a string.

Anyway the way to do this is you declare a structure to keep these things paired:

struct t {string name; int number;};
vector<t> list;
// fill in list

// comparer to compare two such structs
bool comparer(t &a, t &b) { return a.number>=b.number; }

// and to sort the list
sort(list.begin(), list.end(), comparer);

Upvotes: 1

Related Questions