在C ++中按非ASCII顺序的第一个字母对字符串向量进行排序

Posted

技术标签:

【中文标题】在C ++中按非ASCII顺序的第一个字母对字符串向量进行排序【英文标题】:Sorting a vector of strings by the first letter in non-ascii order in C++ 【发布时间】:2016-10-11 06:32:50 【问题描述】:

我有一个包含单词列表的文本文件。

我使用ifstream 将这些单词读入vector,现在我尝试按类似于以下的顺序对它们进行排序:

A a B b C c [...]

我尝试在气泡搜索算法中使用第三个 for 循环来实现这一点,以查看每个单词的第一个字符(我知道这远非最有效的方法,尤其是在我使用大型数据集时)

然后检查字母和下一个字母是大写还是小写,如果大写字母与当前字母相同,则切换,但这似乎不起作用。

void bubble_Sort (vector <string> & words)

  for (unsigned i = words.size(); i >= 2; --i)
  
    for (unsigned k = 0; k + 1 < i; k++)
    
      int hi = k+1;
      string temp1 = words[hi];
      string temp2 = words[k];
      int smallsize = words[hi].size();
      int smallprecedence = 0;

      if (words[k].size() < words[hi].size())
        smallsize = words[k].size();

      for (unsigned j = 0; j < smallsize; j++)
      
        if (temp1[j] >= 'A' && temp1[j] <= 'Z')
        
          if (temp2[j] >='a' && temp2[j] <= 'z')
          
            char lowercase1 = temp1[j] + 32;
            if (lowercase1 == temp2[j])
            
              string temp = words[k];
              words[k] = words[hi];
              words[hi] = temp;
              break;
            
          

          else if (temp2[j] >= 'A' && temp2[j] <= 'Z')
          
            if (temp1[j] < temp2[j])
            
              string temp = words[k];
              words[k] = words[hi];
              words[hi] = temp;
              break;
            
          
        

        if (temp1[j] >= 'a' && temp1[j] <= 'z')
        
          if (temp2[j] >= 'A' && temp2[j] <= 'Z')
          
            char uppercase1 = temp1[j] - 32;
            if (uppercase1 < temp2[j])
            
              string temp = words[k];
              words[k] = words[hi];
              words[hi] = temp;
              break;
            
          

          else if (temp2[j] >= 'a' && temp2[j] <= 'z')
          
            if (temp1[j] < temp2[j])
            
              string temp = words[k];
              words[k] = words[hi];
              words[hi] = temp;
              break;
            
          
        

        else if (temp1[j] == temp2[j] && temp1.size() < temp2.size())
          ++smallprecedence;
      

      if (smallprecedence == smallsize)
      
        string temporary = words[k];
        words[k] = words[hi];
        words[hi] = temporary;
      
    
  

【问题讨论】:

您是否正在实施自己的冒泡排序作为练习?如果没有,你应该使用std::sort并实现比较功能。 是的,我正在尝试使用冒泡排序按 A a B b 等顺序对向量进行排序,即使在 ascii 中 a 大于 B,这是我一直遇到的问题有。 【参考方案1】:

不要重新发明***。只需修改默认比较函数,使 aA

编辑我使用了错误的比较函数。对于&lt;,它应该返回true,对于&gt;=,它应该返回false。这个问题已经解决了

std::vector<std::string> vec;
//
std::sort(vec.begin(), vec.end(), [](const std::string& lhs, const std::string& rhs)
 
   const char* s1=lhs.c_str();
   const char* s2=rhs.c_str();
   while(true) 
     // first ignore case
     if ( std::toupper(*s1) < std::toupper(*s2) ) return true;
     if ( std::toupper(*s1) > std::toupper(*s2) ) return false;
     // end of both strings, exact match
     if ( *s1 == 0 && *s2 == 0 ) return false;
     // compare upper case vs lower case ('A' vs 'a')
     if ( *s1 > *s2) return false;
     if ( *s1 < *s2) return true;
     ++s1; ++s2;
    
);

【讨论】:

【参考方案2】:

首先,摆脱硬编码的 ASCII 主义。 C 和 C++ 早就有判断一个字符是字母、数字、大写还是小写等的函数了,查一下。

其次,清楚地描述决定您希望结果的顺序的因素。

第三,根据该描述,编写一个函数,它接受两个字符串,并告诉您第一个字符串是否应该在第二个之前。在排序中使用那个函数

【讨论】:

【参考方案3】:

您可以使用std::sort 对向量进行排序,并使用std::string::at() 获取对std::string 中第一个字符的引用:

std::vector<std::string> vec;
//
std::sort(vec.begin(), vec.end(), [](const std::string& lhs, const std::string& rhs)
 
    char l_ch, r_ch;
    l_ch = lhs.at(0);
    r_ch = rhs.at(0);
    return l_ch < r_ch;
);

【讨论】:

在使用at()之前最好检查空字符串。 @FrerichRaabe:你说得对,只是提供了一个 sn-p,甚至没有测试代码。 std::compare 可以用于比较,但 OP 坚持第一个字母【参考方案4】:

我认为跳过完全相同的前缀然后用大写比较一次就足够了:

std::vector<std::string> vec;
//
std::sort(vec.begin(), vec.end(), [](const std::string& lhs, const std::string& rhs)
 
  const char* s1=lhs.c_str();
  const char* s2=rhs.c_str();
  while(*s1 && *s1 == *s2) ++s1; ++s2;  
  int rc = toupper(*s1) - toupper(*s2);
  if (rc) return rc;
  return *s1 - *s2;
);

如果您只需要按首字母比较,只需删除while(*s1 &amp;&amp; *s1 == *s2) ++s1; ++s2;

【讨论】:

以上是关于在C ++中按非ASCII顺序的第一个字母对字符串向量进行排序的主要内容,如果未能解决你的问题,请参考以下文章

dplyr:在 R 中按字母顺序排列列

如何在数据库表中按字母顺序对列进行排序? [关闭]

在mysql中按字母顺序对全名进行排序

在Javascript中按字母顺序对字符串进行排序

在Javascript中按字母顺序对字符串进行排序

如何在 swift 中按字母顺序对 JSON 字符串进行排序?