C ++ std :: set <string>字母数字自定义比较器

时间:2016-03-21 07:15:29

标签: c++ algorithm set std comparator

我正在解决String Array的排序非冗余排列问题。 例如,如果输入字符串是"8aC",那么输出应该是{"Ca8","C8a", "aC8", "a8C", "8Ca", "9aC"}的顺序。我选择了C ++数据结构集,因为每次我将String插入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;
    }
}

5 个答案:

答案 0 :(得分:1)

你的比较器是对的。我会像这样将参数转换为const ref

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

从这个简单的实现开始:

return s_left < s_right

这将提供默认行为,让您确信自己走在正确的轨道上。 然后开始比较当时的一个字符和两个字符串长度之间的较短的for循环。您可以使用operator [](例如s_left [i])

简单地删除字符串

答案 1 :(得分:1)

你几乎就在那里,但你应该按字典顺序比较你的字符串。 我粗略地为你的代码添加了一些小改动。

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;
    }
};

答案 2 :(得分:0)

你已经拥有了你所拥有的东西。

在您的比较仿函数中,您将获得两个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函数,它应该全部有效: - )

答案 3 :(得分:0)

对此没有绝对的肯定,但是你可以使用枚举类来获得你的优势或数组,并选择从某些你喜欢的订单中读取。

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

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
       }
     }
    }
}

答案 4 :(得分:0)

这应该有效:

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;
            }
        }
    }