C++ 标准::设置<string>字母数字自定义比较器



我正在解决字符串数组排序非冗余排列的问题。例如,如果输入字符串是"8aC",则输出应该像{"Ca8","C8a", "aC8", "a8C", "8Ca", "9aC"}一样排序。我选择C++数据结构集,因为每次我将字符串插入 std:set 时,set 都会自动排序并消除冗余。输出很好。

但是我想以不同的字母数字顺序对集进行排序,这与默认的字母数字排序顺序不同。我想自定义设置顺序优先级的比较器,例如:upper case> lower case > digit

我试图自定义比较器,但这非常令人沮丧。如何自定义集合的排序顺序?这是我的代码。

set<string, StringCompare> setl;
for (i = 0; i < f; i++)
{
    setl.insert(p[i]); //p is String Array. it has the information of permutation of String.
}
for (set<string>::iterator iter = setl.begin(); iter != setl.end(); ++iter)
       cout << *iter << endl; //printing set items. it works fine.
struct StringCompare
{
    bool operator () (const std::string s_left, const std::string s_right)
    {
        /*I want to use my character comparison function in here, but have no idea about that. 
          I'm not sure about that this is the right way to customize comparator either.*/
    }
};
int compare_char(const char x, const char y)
{
    if (char_type(x) == char_type(y))
    {
        return ( (int) x < (int) y) ? 1 : 0 ;
    }
    else return (char_type(x) > char_type(y)) ? 1 : 0;
}
int char_type(const char x)
{
    int ascii = (int)x;
    if (ascii >= 48 && ascii <= 57) // digit
    {
        return 1;
    }
    else if (ascii >= 97 && ascii <= 122) // lowercase
    {
        return 2;
    }
    else if (ascii >= 48 && ascii <= 57) // uppercase
    {
        return 3;
    }
    else
    {
        return 0;
    }
}

你快到了,但你应该按字典顺序比较你的字符串。我粗略地对您的代码进行了一些小的更改。

int char_type( const char x )
{
    if ( isupper( x ) )
    {
        // upper case has the highest priority
        return 0;
    }
    if ( islower( x ) )
    {
        return 1;
    }
    if ( isdigit( x ) )
    {
        // digit has the lowest priority
        return 2;
    }
    // something else
    return 3;
}
bool compare_char( const char x, const char y )
{
    if ( char_type( x ) == char_type( y ) )
    {
        // same type so that we are going to compare characters
        return ( x < y );
    }
    else
    {
        // different types
        return char_type( x ) < char_type( y );
    }
}
struct StringCompare
{
    bool operator () ( const std::string& s_left, const std::string& s_right )
    {
        std::string::const_iterator iteLeft  = s_left.begin();
        std::string::const_iterator iteRight = s_right.begin();
        // we are going to compare each character in strings
        while ( iteLeft != s_left.end() && iteRight != s_right.end() )
        {
            if ( compare_char( *iteLeft, *iteRight ) )
            {
                return true;
            }
            if ( compare_char( *iteRight, *iteLeft ) )
            {
                return false;
            }
            ++iteLeft;
            ++iteRight;
        }
        // either of strings reached the end.
        if ( s_left.length() < s_right.length() )
        {
            return true;
         }
         // otherwise. 
         return false;
    }
};

你的比较器是对的。我会像这样将参数转换为常量引用

bool operator () (const std::string &s_left, const std::string &s_right)

并从这个简单的实现开始:

return s_left < s_right

这将给出默认行为,并让您确信自己走在正确的轨道上。然后开始将一次的一个字符与两个字符串长度之间较短的 for 循环进行比较。你可以简单地用运算符[]来获取字符串的字符(例如s_left[i])

你几乎拥有你所拥有的东西。

在您的比较函子中,您将获得两个std::string。您需要做的是找到两个字符串不同的第一个位置。为此,您可以使用标准库中的std::mismatch。这将返回一个充满迭代器的std::pair,这些迭代器指向前两个不同的元素:

auto iterators = std::mismatch(std::begin(s_left), std::end(s_left),
                               std::begin(s_right), std::end(s_right));

现在,您可以取消引用我们获得字符的两个迭代器:

char c_left = *iterators.first;
char c_right = *iterators.second;

您可以将这两个字符传递给您的compare_char函数,它应该都可以工作:-)

对此

不是绝对确定,但您可以使用枚举类来发挥自己的优势或数组,并选择从某些索引中读取您喜欢的顺序。

您可以使用一个枚举类来定义要输出数据的顺序,并使用另一个包含要输出的数据的枚举类,然后您可以设置一个不断循环的循环,以排列方式将值分配给输出!

namespace CustomeType
{
    enum Outs { Ca8= 0,C8a, aC8, a8C, 8Ca, 9aC };
    enum Order{1 = 0 , 2, 3 , 4 , 5};   
    void PlayCard(Outs input)
    {
        if (input == Ca8) // Enumerator is visible without qualification
        {
            string[] permuted;
            permuted[0] = Outs[0];
            permuted[1] = Outs[1];
            permuted[2] = Outs[2];
            permuted[3] = Outs[3];
            permuted[4] = Outs[4];
        }// else use a different order
     else if (input == Ca8) // this might be much better
     {
       string[] permuted;
       for(int i = 0; i<LessThanOutputLength; i++)
       {
              //use order 1 to assign values from Outs
       }
     }
    }
}

这应该有效:

bool operator () (const std::string s_left, const std::string s_right)
    {
        for(int i = 0;i < s_left.size();i++){
            if(isupper(s_left[i])){
                if(isupper(s_right[i])) return s_left[i] < s_right[i];
                else if(islower(s_right[i]) || isdigit(s_right[i]))return true;
            }
            else if(islower(s_left[i])){
                if(islower(s_right[i])) return s_left[i] < s_right[i];
                else if(isdigit(s_right[i])) return true;
                else if(isupper(s_right[i])) return false;
            }
            else if(isdigit(s_left[i])){
                if(isdigit(s_right[i])) return s_left[i] < s_right[i];
                else if(islower(s_right[i]) || isupper(s_right[i])) return false;
            }
        }
    }

最新更新