I have an array of structs that I need to retrive data from. The array holds names and scores.
我有一个结构数组,我需要从中检索数据。该数组包含名称和分数。
For one function I have to output the highest score and the name associated. If there are multiple cases I must output all names.
对于一个功能,我必须输出最高分和相关名称。如果有多种情况,我必须输出所有名称。
I CANNOT USE VECTORS or LISTS. (else I would) I just want to perform both actions in the same step.
我不能使用矢量或列表。 (否则我会)我只想在同一步骤中执行两个动作。
This is how I'm handling it:
这就是我处理它的方式:
void highScorer ( player array[], int size )
{ // highScorer
int highScore = 0; //variable to hold the total score
// first loop determines highest score
for ( int i = 0; i < size; i++ ) {
if ( array[i].pointsScored > highScore ) {
highScore = array[i].pointsScored;
}
}
cout << "\nThe highest scoring player(s) were:\n";
// second loop finds players with scores matching highScore and prints their name(s)
for ( int i = 0; i < size; i++ ) {
// when a match is found, the players name is printed out
if ( array[i].pointsScored == highScore ) {
cout << array[i].playerName;
cout << ", scored ";
// conditional will output correct grammar
if ( array[i].pointsScored > 1 ) {
cout << array[i].pointsScored << " points!\n";
}
else {
cout << array[i].pointsScored << " point!\n";
}
}
}
cout << "\n"; // add new line for readability
return;
} // highScorer
I would like to condense this to one for loop. Unless someone has a suggestion for an even more efficient method. I would think sorting the data would be unnecessary. Plus if it's sorted, how could determine if there were more than one "highScore" case in one step.
我想将其浓缩为一个for循环。除非有人建议采用更有效的方法。我认为排序数据是不必要的。另外,如果它已经排序,如何确定一步中是否存在多个“highScore”案例。
6 个解决方案
#1
2
One solution would be to record the names of the players as you're searching for the high score. If it's equal to the current high score, then append an additional name to your "collection of names string", and if it's higher, blank out the names, and record the new high score and new name as well. I'd implement the printout of names as an ostringstream
to ensure you don't run over a buffer. Then when you're done, print out your set of names.
一种解决方案是在您搜索高分时记录玩家的姓名。如果它等于当前的高分,则在您的“名称字符串集合”中附加一个名称,如果它更高,则删除名称,并记录新的高分和新名称。我将名称的打印输出实现为ostringstream,以确保您不会在缓冲区上运行。然后,当你完成后,打印出你的名字。
#2
3
In addition to your highScore
variable you make a second variable, for example a std::list
(or a manual linked list or even a small array, depending on what you're allowed to use). In this list you keep track of the indices of the people that actually have the current highscore. If a new highscore is found you clear that list and add the person with the new highscore. If someone is found that has the highscore you simply add him to the list.
除了你的highScore变量之外,你还可以创建第二个变量,例如std :: list(或手动链接列表,甚至是一个小数组,具体取决于你允许使用的内容)。在此列表中,您可以跟踪实际拥有当前高分的人员的指数。如果找到新的高分,则清除该列表并添加具有新高分的人。如果发现有高分的人,您只需将他添加到列表中即可。
Then after looping you only need to print the players with the indices in this list, rather than find out again who has the highscore.
然后在循环之后,您只需要打印带有此列表中的索引的玩家,而不是再次找出具有高分的人。
#3
1
Keep the set of indexes of the highest score so far as you go through the first (only) pass. Then when you're done, you'll already have the set of indexes that correspond to that highest score. In pseudocode for a language that I just made up:
在您通过第一个(仅)通过时,保留最高分的索引集。然后,当您完成后,您将拥有与该最高分相对应的索引集。在我刚编写的语言的伪代码中:
int highestSoFar = 0;
list indexesOfHighScore = new list();
for (int i = 0; i < scores.count; i++) {
if (scores[i] > highestSoFar) {
highestSoFar = scores[i];
indexesOfHighScore.empty();
}
if (scores[i] == highestSoFar) {
indexesOfHighScore.add(i);
}
}
// Now I know the highest score, and all the indexes of entries that correspond to it.
If you don't have a dynamic list available, the list could be a static array of the same size as the scores array to ensure that it's always big enough.
如果您没有可用的动态列表,则列表可以是与score数组大小相同的静态数组,以确保它总是足够大。
#4
1
Right now your first loop is keeping track of the high score. If it also kept track of all the matching names, you could output the names when the loop was finished. You'd still need a second loop to go through those names, that can't be avoided.
现在你的第一个循环是跟踪高分。如果它还跟踪所有匹配的名称,则可以在循环结束时输出名称。您仍然需要第二个循环来遍历这些名称,这是无法避免的。
#5
1
At a small cost in storage, you can compute the high score and the respective players in the same pass:
只需很少的存储费用,您就可以计算同一传球中的高分和各自的球员:
player ** highScorer ( player array[], int size )
{
player ** result = new player*[size + 1]; // The +1 handles the case where everyone ties
int highScore = 0;
int foundAt = 0;
for ( int i = 0; i < size; i++ )
{
if ( array[i].pointsScored > highScore )
{
highScore = array[i].pointsScored;
foundAt = 0;
}
if ( array[i].pointsScored == highScore )
{
result[foundAt] = &(array[i]);
foundAt++;
}
}
result[foundAt] = null; // Stopping condition, hence the +1 earlier
return result; // Remember to delete[] the resulting array
}
However.
然而。
That won't give you an output. You will still need a second loop if you want to output your results.
这不会给你一个输出。如果要输出结果,仍需要第二个循环。
void outputScores ( player ** result )
{
cout << "\nThe highest scoring player(s) were:\n";
for ( int i = 0; result[i] != null; i++ )
{
cout << result[i]->playerName;
cout << ", scored ";
if ( result[i]->pointsScored == 1 )
cout << "1 point!\n";
else
cout << result[i]->pointsScored << " points!\n";
}
cout << "\n";
delete [] result;
}
To answer your original question, I don't think there is any way whatsoever of finding and outputting all the players having the high score, in a single loop. Even pre-sorting the score array would be worse than what you already have.
为了回答你原来的问题,我认为没有任何方法可以在一个循环中找到并输出所有具有高分的玩家。即使对分数阵列进行预先排序也会比您现有的更糟糕。
#6
0
Rather than keeping the complete set of matching indices, I would just keep the first and last. That lets you skip searching the entire list, and avoids the second pass completely in the case where there's a unique highest score.
我不会保留完整的匹配索引,而是保留第一个和最后一个。这使您可以跳过搜索整个列表,并在有唯一最高分的情况下完全避免第二次传递。
void highScorer( player* array, int size )
{
int highScore = 0;
int firstHighI = -1, lastHighI = -1;
for ( int i = 0; i < size; i++ ) {
if ( array[i].pointsScored > highScore ) {
highScore = array[i].pointsScored;
firstHighI = i;
}
if ( array[i].pointsScored == highScore ) {
lastHighI = i;
}
}
if (firstHighI >= 0) {
std::cout << "\nThe highest scoring player(s) were:\n";
for ( int i = firstHighI; i < lastHighI; i++ ) {
if ( array[i].pointsScored == highScore ) {
std::cout << array[i].playerName << ", ";
}
}
std::cout << array[lastHighI].playerName << " with a score of " << highScore;
if ( highScore != 1 ) {
std::cout << " points!\n";
}
else {
std::cout << " point!\n";
}
}
std::cout << "\n";
}
#1
2
One solution would be to record the names of the players as you're searching for the high score. If it's equal to the current high score, then append an additional name to your "collection of names string", and if it's higher, blank out the names, and record the new high score and new name as well. I'd implement the printout of names as an ostringstream
to ensure you don't run over a buffer. Then when you're done, print out your set of names.
一种解决方案是在您搜索高分时记录玩家的姓名。如果它等于当前的高分,则在您的“名称字符串集合”中附加一个名称,如果它更高,则删除名称,并记录新的高分和新名称。我将名称的打印输出实现为ostringstream,以确保您不会在缓冲区上运行。然后,当你完成后,打印出你的名字。
#2
3
In addition to your highScore
variable you make a second variable, for example a std::list
(or a manual linked list or even a small array, depending on what you're allowed to use). In this list you keep track of the indices of the people that actually have the current highscore. If a new highscore is found you clear that list and add the person with the new highscore. If someone is found that has the highscore you simply add him to the list.
除了你的highScore变量之外,你还可以创建第二个变量,例如std :: list(或手动链接列表,甚至是一个小数组,具体取决于你允许使用的内容)。在此列表中,您可以跟踪实际拥有当前高分的人员的指数。如果找到新的高分,则清除该列表并添加具有新高分的人。如果发现有高分的人,您只需将他添加到列表中即可。
Then after looping you only need to print the players with the indices in this list, rather than find out again who has the highscore.
然后在循环之后,您只需要打印带有此列表中的索引的玩家,而不是再次找出具有高分的人。
#3
1
Keep the set of indexes of the highest score so far as you go through the first (only) pass. Then when you're done, you'll already have the set of indexes that correspond to that highest score. In pseudocode for a language that I just made up:
在您通过第一个(仅)通过时,保留最高分的索引集。然后,当您完成后,您将拥有与该最高分相对应的索引集。在我刚编写的语言的伪代码中:
int highestSoFar = 0;
list indexesOfHighScore = new list();
for (int i = 0; i < scores.count; i++) {
if (scores[i] > highestSoFar) {
highestSoFar = scores[i];
indexesOfHighScore.empty();
}
if (scores[i] == highestSoFar) {
indexesOfHighScore.add(i);
}
}
// Now I know the highest score, and all the indexes of entries that correspond to it.
If you don't have a dynamic list available, the list could be a static array of the same size as the scores array to ensure that it's always big enough.
如果您没有可用的动态列表,则列表可以是与score数组大小相同的静态数组,以确保它总是足够大。
#4
1
Right now your first loop is keeping track of the high score. If it also kept track of all the matching names, you could output the names when the loop was finished. You'd still need a second loop to go through those names, that can't be avoided.
现在你的第一个循环是跟踪高分。如果它还跟踪所有匹配的名称,则可以在循环结束时输出名称。您仍然需要第二个循环来遍历这些名称,这是无法避免的。
#5
1
At a small cost in storage, you can compute the high score and the respective players in the same pass:
只需很少的存储费用,您就可以计算同一传球中的高分和各自的球员:
player ** highScorer ( player array[], int size )
{
player ** result = new player*[size + 1]; // The +1 handles the case where everyone ties
int highScore = 0;
int foundAt = 0;
for ( int i = 0; i < size; i++ )
{
if ( array[i].pointsScored > highScore )
{
highScore = array[i].pointsScored;
foundAt = 0;
}
if ( array[i].pointsScored == highScore )
{
result[foundAt] = &(array[i]);
foundAt++;
}
}
result[foundAt] = null; // Stopping condition, hence the +1 earlier
return result; // Remember to delete[] the resulting array
}
However.
然而。
That won't give you an output. You will still need a second loop if you want to output your results.
这不会给你一个输出。如果要输出结果,仍需要第二个循环。
void outputScores ( player ** result )
{
cout << "\nThe highest scoring player(s) were:\n";
for ( int i = 0; result[i] != null; i++ )
{
cout << result[i]->playerName;
cout << ", scored ";
if ( result[i]->pointsScored == 1 )
cout << "1 point!\n";
else
cout << result[i]->pointsScored << " points!\n";
}
cout << "\n";
delete [] result;
}
To answer your original question, I don't think there is any way whatsoever of finding and outputting all the players having the high score, in a single loop. Even pre-sorting the score array would be worse than what you already have.
为了回答你原来的问题,我认为没有任何方法可以在一个循环中找到并输出所有具有高分的玩家。即使对分数阵列进行预先排序也会比您现有的更糟糕。
#6
0
Rather than keeping the complete set of matching indices, I would just keep the first and last. That lets you skip searching the entire list, and avoids the second pass completely in the case where there's a unique highest score.
我不会保留完整的匹配索引,而是保留第一个和最后一个。这使您可以跳过搜索整个列表,并在有唯一最高分的情况下完全避免第二次传递。
void highScorer( player* array, int size )
{
int highScore = 0;
int firstHighI = -1, lastHighI = -1;
for ( int i = 0; i < size; i++ ) {
if ( array[i].pointsScored > highScore ) {
highScore = array[i].pointsScored;
firstHighI = i;
}
if ( array[i].pointsScored == highScore ) {
lastHighI = i;
}
}
if (firstHighI >= 0) {
std::cout << "\nThe highest scoring player(s) were:\n";
for ( int i = firstHighI; i < lastHighI; i++ ) {
if ( array[i].pointsScored == highScore ) {
std::cout << array[i].playerName << ", ";
}
}
std::cout << array[lastHighI].playerName << " with a score of " << highScore;
if ( highScore != 1 ) {
std::cout << " points!\n";
}
else {
std::cout << " point!\n";
}
}
std::cout << "\n";
}