我有一个包含许多相同形式的字符串的向量:
'12345 QWERTY'
'23456 ASDFGH'
'34567 ZXCVBN'
我需要按代码(int类型)和名称(字符串类型)对它们进行排序。我正在考虑使用.substr()
函数来忽略这些数字。有没有办法在sort函数中使用它?
尝试创建一个映射函数来赞美'sort()':
bool mapFunc(string a, string b)
{
return a.substr(6) < b.substr(6));
}
插入排序功能:
sort(begin, end, mapFunc);
其中'begin'和'end'都是指向vector的开头和结尾的迭代器。
如果我在这里犯了任何错误,请纠正我。)
答案 0 :(得分:3)
通过将自定义谓词传递给std::sort()
,您处于正确的轨道上。你只需要更多地充实它:
void split(const string &s, int &code, string &name) {
size_t idx = s.find(' ');
code = stoi(s.substr(0, idx));
name = s.substr(idx+1);
}
bool mapFunc(const string &a, const string &b) {
int code1, code2;
string name1, name2;
split(a, code1, name1);
split(b, code2, name2);
if (code1 == code2)
return name1 < name2;
return code1 < code2;
}
这将首先按照数字代码对矢量项进行排序,并仅按名称对具有相同代码值的项进行排序。
答案 1 :(得分:2)
您可以使用functor
(函数对象):
struct Compare_By_Number
{
bool operator()(const std::string& a, const std::string& b) const
{
std::istringstream a_input_stream(a);
std::istringstream b_input_stream(b);
int a_value, b_value;
a_input_stream >> a_value;
b_input_stream >> b_value;
return a_value < b_value;
}
};
然后,您可以根据the std::sort
example传递函数的实例。
编辑1:独立功能
另一种方法是将代码放在独立函数中并传递函数:
bool Order_By_Number(const std::string& a, const std::string& b)
{
std::istringstream a_input_stream(a);
std::istringstream b_input_stream(b);
int a_value, b_value;
a_input_stream >> a_value;
b_input_stream >> b_value;
return a_value < b_value;
}
std::vector<std::string> database;
//...
std::sort(database.begin(), database.end(), Order_By_Number);
如果第一个参数位于您订购的第二个参数之前,则基本概念是返回true
。
答案 2 :(得分:1)
我认为使用std::lexicographical_compare提取子字符串会更有效。
std::lexicographical_compare的作用是比较 到位 的子字符串,因此您无需支付将其复制出来的费用。
这样的事情:
std::vector<std::string> v
{
"12345 QWERTY",
"23456 ASDFGH",
"34567 ZXCVBN",
};
std::sort(std::begin(v), std::end(v), [](std::string const& a, std::string const& b){
return std::lexicographical_compare(std::begin(a), std::begin(a) + 5, std::begin(b), std::begin(b) + 5);
});
std::cout << "By first column" << '\n';
for(auto const& s: v)
std::cout << s << '\n';
std::sort(std::begin(v), std::end(v), [](std::string const& a, std::string const& b){
return std::lexicographical_compare(std::begin(a) + 6, std::end(a), std::begin(b) + 6, std::end(b));
});
如果您要做很多这样的事情,那么您可以将它包装在一个特殊的比较器中:
struct substring_compare
{
std::size_t from;
std::size_t len;
substring_compare(std::size_t from, std::size_t len)
: from(from), len(len) {}
bool operator()(std::string const& a, std::string const& b) const
{
// sanity checks
assert(from + len <= a.size());
assert(from + len <= b.size());
auto beg_a = std::begin(a) + from;
auto end_a = beg_a + len;
auto beg_b = std::begin(b) + from;
auto end_b = beg_a + len;
return std::lexicographical_compare(beg_a, end_a, beg_b, end_b);
}
};
int main()
{
std::vector<std::string> v
{
"12345 QWERTY",
"23456 ASDFGH",
"34567 ZXCVBN",
};
// start at position 0, comparing 5 characters
std::sort(std::begin(v), std::end(v), substring_compare(0, 5));
std::cout << "By first column" << '\n';
for(auto const& s: v)
std::cout << s << '\n';
// start at position 6, comparing 6 characters
std::sort(std::begin(v), std::end(v), substring_compare(6, 6));
std::cout << "By second column" << '\n';
for(auto const& s: v)
std::cout << s << '\n';
}
<强>输出:强>
By first column
12345 QWERTY
23456 ASDFGH
34567 ZXCVBN
By second column
23456 ASDFGH
12345 QWERTY
34567 ZXCVBN
答案 3 :(得分:1)
您可以使用std::pair
提供的现有功能(比较运算符)。所以实现转换功能:
std::pair<int,std::string> convert( const std::string &str )
{
int id = 0;
std::string name;
std::istringstream is( str );
is >> id >> name;
return std::make_pair( id, name );
}
然后你的比较器功能很简单:
bool compare( const std::string &s1, const std::string &s2 )
{
return convert( s1 ) < convert( s2 );
}
答案 4 :(得分:0)
你最好有std::vector<std::pair<int, string>>
来消除这些并发症。
否则,您应该创建比较函数并传递子字符串。
答案 5 :(得分:0)
要设置问题,我们有一个字符串向量:
vector<string>myVec;
vector<string>::iterator vecBegin=myVec.begin(), vecBegin=myVec.end();
尝试创建一个映射函数来赞美'sort()':
bool mapFunc(string a, string b)
{
return a.substr(6) < b.substr(6));
}
插入排序功能:
sort(vecBegin, vecEnd, mapFunc);
其中'vecBegin'和'vecEnd'都是指向向量开头和结尾的迭代器。
这将通过子串对字符串向量进行排序。可以使用迭代器访问该向量:
vector<string>::iterator currentVec;
for (currentVec=vecBegin; currentVec<vecEnd; ++currentVec)
{
// Do things
}