在尊重数字的同时对集合元素进行排序



我知道C++std::set保持其元素的排序。如何在尊重数值的同时保持这些元素的排序?

我面临的问题是,如果我尝试添加元素K1K2K10,例如,在集合将它们排序为字符串后,它们会得到以下顺序:

K1
K10
K2

然而,我希望它们按以下顺序排列:

K1
K2
K10

我该怎么做?

在这种情况下,集合确实是按照字典顺序存储字符串的——只是碰巧这不是你想要的顺序。相反,您希望排序在比较事物时以数字处理数字。

有几种方法可以做到这一点。这里有一种方法,它通过将字符串中的每个数字视为一个单独的实体来进行比较。

struct NumericCompare {
bool operator()(const std::string& left, const std::string& right) {
std::istringstream lhs(left), rhs(right);
while (lhs.peek() != EOF && rhs.peek() != EOF) {
/* Do we see digits in either of these? */
if (std::isdigit(lhs.peek() || std::isdigit(rhs.peek()) {
/* If one is a digit and the other isn't, compare the
* characters as usual.
*/
if (!std::isdigit(lhs.peek()) || !std::isdigit(rhs.peek())) {
return lhs.peek() < rhs.peek();
}
/* Otherwise, we have two numbers. Read them both and compare
* them. Note: This assumes numbers are nonnegative and 64-bit,
* which may not be true in your case.
*/
std::uint64_t leftN, rightN;
lhs >> leftN;
rhs >> rightN;
if (lhs != rhs) return lhs < rhs;
}
/* Neither are numbers. Compare as usual. */
auto leftC  = lhs.get();
auto rightC = rhs.get();
if (leftC != rightC) return leftC < rightC;
}
/* At least one stream is empty. See if they both are. */
if (lhs.peek() == EOF && rhs.peek() == EOF) return false;
/* So exactly one of them is. lhs comes before rhs if it's empty. */
return lhs.peek() == EOF;
}
};

从这里,你可以制作类似的东西

std::set<std::string, NumericCompare> mySet;

以这种方式进行比较。

最新更新