[英]Custom Sort on an array of Strings
Given an array of strings containing the seven colors of the rainbow but placed in random order, I am somehow supposed to sort this array to output Red, Orange, Green,....,Violet in that order. 给定一个包含彩虹的七种颜色但以随机顺序排列的字符串数组,我应该以某种方式对该数组进行排序,以按该顺序输出Red,Orange,Green .... Violet。 The order of rainbow colors.
彩虹色的顺序。 How can I sort this array?
如何排序此数组?
You should write a custom comparator. 您应该编写一个自定义比较器。 Here's how I would go about it.
这就是我要做的。
//somewhere in initalization code;
std::map<string, int> mapOrder;
mapOrder["red"] = 1;
mapOrder["orange"] = 2;
...
mapOrder["violet"] = 7;
bool isRainbowLess(const std::string& a, const std::string& b)
{
return mapOrder[a] < mapOrder[b];
}
int main()
{
std::vector<std::string> myVector;
....
std::sort(myVector.begin(), myVector.end(), &isRainbowLess);
}
OK, please do not down vote it right away. 好的,请不要马上对其投下反对票。 I know this is a bad example.
我知道这是一个不好的例子。 I wrote it be cause OP specifically asked for a no-STL solution, and to present how (bad) would/could it look like.
我写这是因为OP专门要求提供无STL解决方案,并说明了它的(坏)情况。
Well, there you go. 好吧,你去。 The code is not completed.
代码未完成。 But you should get the general idea.
但是您应该了解一般的想法。 One thing I did skip is the sorting of integers itself.
我跳过的一件事是整数本身的排序。 Since it should be trivial.
既然应该是琐碎的。 As you can see, the mapping, is a little bit of PIA and looks quite bad.
如您所见,映射只是一点点PIA,看起来很糟糕。 But since you forbid to use STL there is no
std::map
. 但是由于您禁止使用STL,所以没有
std::map
。 Moreover, I implied static size of N
for all the tables. 此外,我暗示所有表的静态大小为
N
It could be allocated dynamically, no problem, and no std::vector
. 它可以动态分配,没有问题,也没有
std::vector
。
I used else if
s for map*
functions to mimick std::map
functionality. 我将
else if
s用于map*
函数来模仿std::map
功能。 Probably switch ... case
could be used, but it should work pretty much the same on a decent compiler. 也许可以使用
switch ... case
,但是在一个不错的编译器上它应该几乎一样工作。
The code I wrote below is pretty much the same in terms of functionality provided as Armen's does. 就提供的功能而言,我下面编写的代码与Armen的代码几乎相同。 I would recommend his solution.
我会推荐他的解决方案。 I skipped same parts.
我跳过了相同的部分。 So you can see it's uglier and more typing.
因此,您可以看到它更丑陋且输入更多。 It looks almost like pure C. Maybe with one modification if you really yearn for speed at very large cases.
它看起来几乎像纯C。如果您真的想在非常大的情况下提高速度,也许可以进行一次修改。 That would be using a temporary data structure that would hold mapped values, to sort it, and then map it back.
那将使用一个临时数据结构,该结构将保留映射的值,对其进行排序,然后再将其映射回去。 Precisely I would advise to avoid calling
map::operator[](const &T)
(or any accessor) on std::string
under high performance constraints to avoid hash computations. 确切地说,我建议避免在高性能约束下在
std::string
上调用map::operator[](const &T)
(或任何访问器),以避免哈希计算。 But that's only it. 但是,仅此而已。
There is also some more to discuss. 还有更多的讨论。 Like what if you wanted two colors to have the same value, or use non-integer weights.
例如,如果您希望两种颜色具有相同的值,或者使用非整数权重。 STL based solution is way more adaptable.
基于STL的解决方案更具适应性。
Cheers. 干杯。
The code: 代码:
/* This will map color literals (color names) to integers, which will associate them with
a numerical value, than can be used for comparison */
enum Colors { Red, Orange, Green, /*...*/ Violet };
/* this should read colors as std::string instances from the input array and assing
the the appropriate color codes into output array at corresponding indexes */
void mapString2Color( const std::string* input, int* output, size_t N ){
for(size_t i = 0; i < N; i++){
if ( input[i] == std::string("red") ) output[i] = Colors::Red;
else if ( input[i] == std::string("orange") ) { output[i] = Colors::Orange; }
else if ( input[i] == std::string("green") ) { output[i] = Colors::Green; }
/*...*/
else if ( input[i] == std::string("violet") ) { output[i] = Colors::Violet; }
else {/*unspecified color code */}
}
}
/* this is supposed to do the opposite to mapString (i.e. put appropriate
string at output[i] based on input[i]) */
void mapColor2String( const int* input, std::string* output, size_t N ){
for(size_t i = 0; i < N; i++){
if ( input[i] == Colors::Red ) output[i] = std::string("red");
else if ( input[i] == Colors::Orange ) { output[i] = std::string("orange"); }
else if ( input[i] == Colors::Green ) { output[i] = std::string("green"); }
/*...*/
else if ( input[i] == Colors::Violet ) { output[i] = std::string("violet"); }
else {/*unspecified color index*/}
}
}
void sort(int* array, size_t N){
/* any in-place sort of your liking for table of (unsigned) integers */
}
main(){
std::string[N] input_array;
std::string[N] output_array;
int[N] temp_array;
//map (translate) colors to their numerical values
mapString2Color(input_array, temp_array, N);
//sort it
sort(temp_array, N);
//map (translate) the values back to color names
mapColor2String(temp_array, output_array, N);
}
First thing I would do is to create a mapping. 我要做的第一件事是创建映射。 You could do this either via a map or by linearly iterating over a presorted array of strings and taking the index of the matching entry.
您可以通过映射或线性迭代预排序的字符串数组并获取匹配条目的索引来执行此操作。 A very simple way (for demonstration purposes really) might be simply to encode the logic into an encapsulated function as follows:
一种非常简单的方法(实际上只是出于演示目的)可能是将逻辑编码为封装的函数,如下所示:
int intForCol( const string& col )
{
if ( col == "red" ) return 0;
else if ( col == "orange" ) return 1;
else if ( col == "yellow" ) return 2;
else if ( col == "green" ) return 3;
else if ( col == "blue" ) return 4;
else if ( col == "indigo" ) return 5;
else if ( col == "violet" ) return 6;
throw "Invalid colour";
}
This will provide an ordering integer based on the input string. 这将基于输入字符串提供一个排序整数。 The next step is to create a comparator:
下一步是创建一个比较器:
int colComp( const string& lhs, const string& rhs )
{
return intForCol( lhs ) - intForCol( rhs );
}
This will allow us to compare strings together returning negative if lhs
< rhs
and positive if lhs
> rhs
这将使我们能够比较字符串连接在一起返回负,如果
lhs
< rhs
和正面的,如果lhs
> rhs
This can now be used within the STL - either as the comparitor within an associative container or directly in a sort algorithm - with relative ease. 现在,可以相对轻松地在STL中使用它(将其用作关联容器中的比较器,或者直接在排序算法中使用)。 Alternatively, if using STL is out of the question or the point of this is to understand how sorting works, you could implement your own sort like the simple and (very) inefficient algorithm below:
另外,如果无法使用STL或这样做的目的是了解排序的工作原理,则可以实现自己的排序,例如下面的简单(非常低效)算法:
const int col_size = 7;
string input[col_size];
input[0] = "indigo";
input[1] = "green";
input[2] = "red";
input[3] = "blue";
input[4] = "yellow";
input[5] = "violet";
input[6] = "orange";
// simple bubble sort
int passes = col_size;
int last = col_size;
while ( passes-- )
{
for ( int i = 0; i < last - 1; ++i )
if ( colComp( input[i], input[i+1] ) > 0 )
{
string temp = input[i]; input[i] = input[i+1]; input[i+1] = temp;
}
last--;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.