Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

map sort question

Posted on 2005-04-28
13
Medium Priority
?
385 Views
Last Modified: 2010-04-01
I map with the key that consists of 2 strings. I need to sort this map sometimes by the either 1st string or sometimes by second string. How do I do this?
Does it make sense to create a key class that has 2 string variables and do it with this class?
Here is an example of what I need, the second string part of my key is rating and my sort specifically needs to be
1) AAA
2) AA
3) A
4) BBB
5) BB
6) B

Is there a way to override map to allow me to sort specifically for the case above?
I need to somehow be able to override sort that map uses. Or is there a better way?

Thanks in advance
0
Comment
Question by:healingtao
13 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 13891958
It IMHO would be easier and more effective to use two maps that have their own sort order and store refereces to the objects that you want them to hold.
0
 
LVL 15

Expert Comment

by:efn
ID: 13892241
>  I need to sort this map sometimes by the either 1st string or sometimes by second string.

This is a bit ambiguous.  If you mean that you want to read entries from the map in key sequence and you want to be able to read it in two different sequences defined by two different keys, then I agree with jkr that you should use two maps as indexes to objects.

However, if you mean you want one sequence where the ordering takes two strings into account, then you are on the right track.  You should create a key class that contains two strings and define an operator < for that class.  You can make that operator do whatever you want, and the map will automatically use it to order objects by these keys.
0
 
LVL 5

Expert Comment

by:rendaduiyan
ID: 13892342
STL sort recieve functor(or function) as parameters, by which you can you can decide the sort algorithm.
bool sort_1st_string(const Key& k1, const Key& k2)
{
    return k1.str1 < k2.str2;
}

bool sort_2nd_string(const Key& k1, const Key& k2)
{
   return k1.str2 < k2.str2;
}

sort(map.begin(), map.end(), sort_1st_string);

sort(map.begin(), map.end(), sort_2nd_string);
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 15

Expert Comment

by:efn
ID: 13892597
> sort(map.begin(), map.end(), sort_1st_string);

Sorry, this won't work.  Map iterators are birectional iterators, the sort function requires random-access iterators, and a bidirectional iterator can't take the place of a random-access iterator.
0
 
LVL 9

Expert Comment

by:jhshukla
ID: 13894495
>> Sorry, this won't work.  Map iterators are birectional iterators, the sort function requires random-access iterators, and a bidirectional iterator can't take the place of a random-access iterator.

what if overload the iterator using a wrapper or derived class.
0
 

Author Comment

by:healingtao
ID: 13894634
I definitely want one sequence where the ordering takes two strings into account.
So you're saying I should create a key class and have logic like return key1.string1 < key2.string2 ??

but I want key1.string1 to have specific order like I mentioned
1) AAA
2) AA
3) A
4) BBB
5) BB
6) B
7) blank
and also if there is a blank for this string, I want it last as shown above.

How do I do this? because when I don't sort it at all by default the order is
1) blank
2) A
3) AA
4) AAA
5) B
6) BB
7) BBB

Thanks
0
 

Author Comment

by:healingtao
ID: 13894925
I forgot to mention that the string previously mentioned is the second part of my key.
The first part should be sorted alphabetically. For example,

String1                                  String2
ABS                                   AAA
ABS                                   AA
ABS                                   A
ABS                                   BBB
ABS                                   BB
ABS                                   B
ABS TOTAL      
AWL                                   AAA
AWL                                   AA
AWL                                   A
AWL                                       BBB
AWL                                       BB
AWL                                       B
AWL TOTAL      

where string1 and string2 is one key

thanks
0
 
LVL 15

Expert Comment

by:efn
ID: 13895149
>>> Sorry, this won't work.  Map iterators are birectional iterators, the sort function requires random-access iterators, and a bidirectional iterator can't take the place of a random-access iterator.

> what if overload the iterator using a wrapper or derived class.

That could be done, but it turns out that sorting in two different sequences is not what the questioner wants, so it's not very relevant at this point.

healingtao,

The usual approach to sorting by two keys is something like this pseudo code:

bool less(key1, key2)
{
  if key1.part1 == key2.part1
    return key1.part2 < key2.part2
  else return key1.part1 < key2.part2
}

You only look at the secondary parts of the keys when the primary parts are equal.

In your case, you would have a more complex test for the secondary parts.

If you know that the empty secondary keys are always with total lines and total lines will be unique, you can ignore empty secondary keys in the sort function, because these lines will always be sorted by their primary keys.

If you do that, the sort logic for the secondary keys could first look at the initial characters of the two keys it is comparing.  If they are different, return a value based on comparing them.  If they are the same, return a value based on comparing their lengths.

--efn
0
 
LVL 15

Expert Comment

by:efn
ID: 13895176
That should have been:

If they are different, return a value based on comparing the initial characters.  If they are the same, return a value based on comparing the lengths of the key strings.
0
 

Author Comment

by:healingtao
ID: 13896829
Here is my code for Key class, can you please confirm that I didn't miss anything.
It seems to be working but I'm sure I missed a few things

#if !defined(RISKKEY__INCLUDED_)
#define RISKKEY__INCLUDED_
#include <string>

class RiskKey {
public:
      RiskKey(){}
      RiskKey(std::string strSector, std::string strCreditRating)
      {
            m_strSector = strSector;
            m_strCreditRating = strCreditRating;
      }
      virtual ~RiskKey(){}
      inline const std::string& getSector() const { return m_strSector;}
      inline void setSector(std::string& strSector) {m_strSector = strSector;}
                inline  const std::string& getCreditRating() const { return m_strCreditRating;}
      inline void setCreditRating(std::string& strCreditRating) {m_strCreditRating = strCreditRating;}
      
      friend inline bool operator<(const RiskKey &key1, const RiskKey &key2)
      {
            if (key1.getSector() != key2.getSector())
                  return (key1.getSector() < key2.getSector());
            
            if (key1.getCreditRating() != key2.getCreditRating())
            {
                  if (key1.getCreditRating().substr(0,1) == key2.getCreditRating().substr(0,1))
                  {
                        if (key1.getCreditRating().length() > key2.getCreditRating().length())
                              return true;
                        else
                              return false;
                  }
                  else
                  {
                        return (key1.getCreditRating() < key2.getCreditRating());
                  }
            
            }
      }

private:
      std::string                  m_strSector;
      std::string                  m_strCreditRating;
};

#endif
0
 
LVL 15

Expert Comment

by:efn
ID: 13899428
The only significant problem I see is that the comparison function doesn't deal with the case where the sectors are equal and the credit ratings are equal.  If you know there will not be any such records, I guess that's OK.
0
 

Author Comment

by:healingtao
ID: 13899504
efn,

In the case they are equal, do I return true or false?
0
 
LVL 15

Accepted Solution

by:
efn earned 2000 total points
ID: 13899523
In that case, it is not true that key1 < key2, so return false.
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

564 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question