将二维字符串数组与std::sort进行比较

compare 2 dimensional string array with std::sort

本文关键字:std sort 比较 数组 字符串 二维      更新时间:2023-10-16

我有一个字符串数组,里面有我想排序的数字(我只想对[I][0]进行排序):

string test[4][2];
test[0][0] = "3";
test[0][1] = "4";
test[1][0] = "1";
test[1][1] = "2";
test[2][0] = "6";
test[2][1] = "8";
test[3][0] = "5";
test[3][1] = "4";
std::sort(std::begin(test), std::end(test), NumericGreaterThan);
bool NumericGreaterThan(const string u[], const string v[])
{
    // more code ..
    return true;
}

结果应该是:

1 - 2
3 - 4
5 - 4
6 - 8

编译器说:[Error] invalid array assignment

更新

上面的例子只是一个测试用例。事实上,我的第2个数组维度比示例中的要宽。例如:

string test[4][2];
test[0][0] = "3";
test[0][1] = "Name";
test[0][2] = "Name";
test[0][3] = "5";

基于@coincoin的解决方案,我做了这样的事情:

// create tmp array with index and sorting value
int testsCount = sizeof(test) / sizeof(test[0]);    
vector< pair<string, string> > tmpTest;
for (int i = 0; i < testsCount; i++) {
    pair<string, string> aPair;
    aPair.first = std::to_string(i);
    aPair.second = test[i][3];  
    tmpTest.push_back(aPair);
}
// sort 
std::sort(std::begin(tmpTest), std::end(tmpTest), compare);
bool compare(const pair<string, string>&i, const pair<string, string>&j)
{
    return std::stoi(i.second)>std::stoi(j.second);
}

现在我有一个test的复制和排序向量,我可以使用它来循环遍历原始测试数组。

for (int i = 0; i < testsCount; i++) {
    cout << i+1 << ". " << test[std::stoi(tmpTest[i].first)][0] << endl;
}

我知道这不是实现这一目标的最佳方式,但它符合我的需求。

我认为你不必要地把事情过于复杂了(还有一些答案…)

您应该修改您的代码设计。

例如,你可以简单地使用一个成对的数组,你可以重用内置的bool operator< (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs),它可以做你想做的事情。。。

#include <array>
#include <algorithm>
int main() {
    std::array<std::pair<int,int>, 4> test { std::make_pair(3,4), std::make_pair(1,2), std::make_pair(6,8), std::make_pair(5,4) };
    std::sort(std::begin(test), std::end(test));
}

实时代码

输出为

(1,2)(3,4)(5,4)(6,8)

仅此而已。。。

为了对数组进行排序,必须将一个数组分配给另一个数组,这是不可能的。您可能应该使用一个成对的数组并比较成对。

您可以将字符串的每一部分分为不同的类,然后只寻址排序函数中最低的子类。这有点复杂,但回答了你的问题。

请注意:此方法只允许迭代最低的子类。我不建议在实际使用中使用此方法,因为它不可扩展,并且随着应用程序的维度结构的增加,它会变得越来越复杂。对于每个新的维度,你都需要一个新的类(随着你的"数组变得越来越n维",这变得越来越乏味)。

            #include <iostream>
            #include <string>
            #include <vector>
            using namespace std;
            class string_container_length {
            public:
                string_container_length(int &length)
                {
                    level2.resize(length);
                }
                // Level to iterated [i][0] where i is important.
                std::vector<std::string> level2;
            };
            class string_container {
            public:
                string_container(int &length, int &width)
                {
                    level1.reserve(width);
                    for (int i = 0; i < width; ++i)
                    {
                        // Creates a new string_container_length using constructor with a set length.
                        level1.push_back(string_container_length(length));
                    }
                }
                std::vector<string_container_length> level1;
            };

            int main(){
                // Will not be iterated in example.
                int length = 2;
                // Will be iterated in example
                int width = 4;
                string_container test(length,width);
                test.level1[0].level2[0] = 7;
                test.level1[0].level2[1] = 4;
                test.level1[0].level2[2] = 3;
                test.level1[0].level2[3] = 8;
                // Passes beginning and end positions to the child class.
                std::sort(std::begin(test.level1[0].level2), std::end(test.level1[0].level2));
            }

推荐:在另一个命名空间下专门为您的需要编写自己的自定义排序函数。这可以使用一个简单的循环、几个if语句和您已经存在的NumericGreaterThan()函数来完成。关于排序函数如何工作的示例和教程可以在这里找到。

首选std::array<>而非C阵列:

auto test = std::array<std::array<std::string, 2>, 4>{{"3"s, "4"s},
                                                      {"1"s, "2"s},
                                                      {"6"s, "8"s},
                                                      {"5"s, "4"s}};
std::sort(std::begin(test), std::end(test), NumericGreaterThan);
auto NumericGreaterThan(const std::array<std::string, 2>& u, const std::array<std::string, 2>& v)
-> bool
{
    // more code ..
    return true;
}

这是未经测试的代码!

在介绍C++习语之前,许多教科书都会先教你C风格。我认为,那些人做得不对。

如果这是唯一一个使用NumericGreaterThan:的地方,也可以考虑使用Lambdas

auto test = std::array<std::array<std::string, 2>, 4>{{"3"s, "4"s},
                                                      {"1"s, "2"s},
                                                      {"6"s, "8"s},
                                                      {"5"s, "4"s}};
std::sort(std::begin(test), std::end(test),
          [](const std::array<std::string, 2>& u, const std::array<std::string, 2>& v)
          -> bool {
              // more code ..
              return true;
          });

如果您已经使用了C++14,那么您可以使用通用Lambda,这会使代码变得更简单一点:

auto test = std::array<std::array<std::string, 2>, 4>{{"3"s, "4"s},
                                                      {"1"s, "2"s},
                                                      {"6"s, "8"s},
                                                      {"5"s, "4"s}};
std::sort(std::begin(test), std::end(test),
          [](const auto& u, const auto& v) -> bool {
              // more code ..
              return true;
          });

还请考虑在排序之前将字符串数组转换为数字。这显著减少了array<string>->int转换的次数:

int convertToNumber(std::array<std::string, 2>);
auto test =
    std::array<std::pair<std::array<std::string, 2>, int> 4>{{{"3"s, "4"s}, 0},
                                                             {{"1"s, "2"s}, 0},
                                                             {{"6"s, "8"s}, 0},
                                                             {{"5"s, "4"s}, 0}};
for(auto& i: test) i.second = convertToNumber(i.first);
std::sort(std::begin(test), std::end(test),
          [](const auto& u, const auto& v) -> bool {
              return u.second > v.second;
          });