【问题标题】:C++ - Sorting strings in a vector in a specific wayC++ - 以特定方式对向量中的字符串进行排序
【发布时间】:2021-03-18 13:35:54
【问题描述】:

我目前正在尝试对向量中的字符串进行排序,但我不确定如何以特定方式进行。我正在使用的游戏引擎要求对字符串进行不区分大小写的排序(我已经能够完成)。它还会对这些文件名进行排序,下划线位于字母之前。

例如,这些字符串目前排序如下:

ChallengeBattleships.bsf
ChallengeBattleships.zip
ChallengeBattleshipsPause.bsf
ChallengeBattleshipsSummary.bsf
ChallengeBattleshipsSurface.bsf
ChallengeBattleships_arena.bsf
ChallengeBattleships_day.zip

但我需要像这样对它们进行排序(以及不区分大小写):

ChallengeBattleships.bsf
ChallengeBattleships.zip
ChallengeBattleships_arena.bsf
ChallengeBattleships_day.zip
ChallengeBattleshipsPause.bsf
ChallengeBattleshipsSummary.bsf
ChallengeBattleshipsSurface.bsf

有谁知道如何以这种方式对向量中的字符串进行排序?

【问题讨论】:

  • std::sort。始终std::sort。然后使用合适的lambda 进行比较。
  • 除此之外,为什么需要对这个文件名列表进行排序?为什么你想要它们的顺序特别,这个顺序应该解决什么问题?
  • 一种可能性是创建字符串对,第一部分对应于下划线之前的名称,第二部分对应于下划线之后。然后借助这些对和专用 lambda 函数对原始字符串进行排序
  • std::sort 做你想做的事。如果不符合您的要求,您应该给出排序规则或者您需要自己创建。
  • @Someprogrammerdude 我正在修改的游戏对这些字符串在我正在创建的文件存档中列出的顺序非常挑剔。当我从外部驱动器上的文件生成存档时,我意识到了这一点。由于某种原因,这些文件最终被正确排序(可能是按创建日期?这些文件是从游戏的原始文件档案之一中按顺序转储的)。当我尝试将新文件添加到存档中时,这些文件被放在列表的末尾,而不管它们的名称。游戏不会加载新文件,所以我认为字符串顺序很重要

标签: c++ string sorting vector


【解决方案1】:

将 std::sort 与 lambda 一起使用。 如果不修改原始字符串,则:

std::sort(vec.begin(), vec.end(), 
         [](std::string s1, std::string s2){
             std::transform(s1.begin(), s1.end(), s1.begin(),
                   [](char c){ return std::tolower(c); });
             std::transform(s2.begin(), s2.end(), s2.begin(),
                   [](char c){ return std::tolower(c); });
             return s1 < s2;
         });

改变大小写: How to convert std::string to lower case?

【讨论】:

  • 那'_'呢?
  • - tolower 方法将保持下划线不变。并且由于下划线 ASCII 值低于所有字母,它将首先按 w.r.t 排序。字符串中该位置的任何内容。
  • 啊,下划线是比小写字母低的 ASCII,但不是大写字母,因此它适用于 tolower 情况。
【解决方案2】:

您要求的是自定义字典顺序。一种可能性是使用#include &lt;algorithm&gt; 中的字典比较助手,它接受自定义比较器。例如。喜欢下划线的东西高于一切:

#include <algorithm>
#include <iostream>

namespace {
std::vector<std::string> names = {
  "ChallengeBattleships_day.zip",
  "ChallengeBattleships.bsf",
  "ChallengeBattleshipsSummary.bsf",
  "ChallengeBattleshipsPause.bsf",
  "ChallengeBattleships_arena.bsf",
  "ChallengeBattleships.zip",
  "ChallengeBattleships_day.zip",
  "ChallengeBattleshipsSurface.bsf"
};

// custom char ordering
bool UnderscoreSupporter(char lhs, char rhs) {
  if (lhs == rhs) return false;
  if (lhs == '_') return true;  // '_' is smaller than everything !
  if (rhs == '_') return false; // nothing is smaller than '_' !
  
  return (lhs < rhs); // default lexicographical ordering
}
}

int main()
{

  std::cout << "Original order: " << std::endl;
  for (const auto& str : names) std::cout << str << std::endl;
  std::cout << std::endl;

  // lambda to compare strings using our custom ordering
  auto sorting_fct = [](const std::string& s1, const std::string& s2) {
    return std::lexicographical_compare(s1.cbegin(), s1.cend(), s2.cbegin(), s2.cend(), UnderscoreSupporter);
  };

  // sort names based on that lambda
  std::sort(names.begin(), names.end(), sorting_fct);

  std::cout << "New order: " << std::endl;
  for (const auto& str : names) std::cout << str << std::endl;
  std::cout << std::endl;

  return 0;
}

我会让你添加“忽略大小写”部分,但这应该是直接使用例如tolower 来自&lt;cctype&gt;

【讨论】:

    猜你喜欢
    • 2019-04-25
    • 1970-01-01
    • 2018-09-28
    • 2016-07-29
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多