修剪字符串向量

时间:2011-01-09 22:43:36

标签: c++ string vector

我的std::vector std::strings包含与此类似的数据:

[0] = ""
[1] = "Abc"
[2] = "Def"
[3] = ""
[4] = "Ghi"
[5] = ""
[6] = ""

如何获得包含1到4个4个字符串的向量? (即我想从向量的开头和结尾修剪所有空白字符串):

[0] = "Abc"
[1] = "Def"
[2] = ""
[3] = "Ghi"

目前,我正在使用一个前向迭代器来向"Abc"和一个反向迭代器返回"Ghi",然后使用这些迭代器构造一个新的向量。这种方法有效,但我想知道是否有更简单的方法来修剪这些元素。

P.S。我是C ++ noob。

修改

另外,我应该提到矢量可能完全由空字符串组成,在这种情况下,0大小的矢量将是所需的结果。

5 个答案:

答案 0 :(得分:2)

如何使用谓词:

class StringNotEmpty
{
  bool operator()(const std::string& s) { return !s.empty(); }
};

现在修剪:

vec.erase(std::find_if(vec.rbegin(), vec.rend(), StringNotEmpty()).base(), vec.end());
vec.erase(vec.begin(), std::find_if(vec.begin(), vec.end(), StringNotEmpty()));

.base()电话可能有一个一个接一个,但一般的想法应该有效。

答案 1 :(得分:0)

你的方法是合理的。另一种方法是找到第一个字符串,然后将所有连续的字符串复制到向量中的开始(和后续)元素,之后修剪向量的结尾。

除非这是一段关键的代码,这会降低您的应用程序速度,否则它的工作重要性比您实现最有效的实现更重要。

答案 2 :(得分:0)

你所做的一切都很好。但是,如果您希望“就地”缩短单个容器而不是制作子范围的副本,则erase可以vector其他范围。

// Probably similar to what you already have: Find iterators for the range to keep.
std::vector<std::string>::iterator start=strs.begin(), stop=strs.end();
start = strs.begin();

while (start != stop && start->empty()) ++start;
if (start == stop) {
  // all strings were empty!
  strs.clear();
} else {
  while (start != --stop && stop->empty()) ;
  ++stop;

  // std::vector<std::string>(start, stop) is the desired subrange
  strs.erase(stop, strs.end());
  strs.erase(strs.begin(), start);
}

但我同意@Nathan:如果你已经拥有的东西对你比对此更有意义,那么请保留它,除非你知道或强烈怀疑会涉及到很多字符串。

答案 3 :(得分:0)

typedef std::vector<std::strings> Strings;

Strings myStrings;
//... currently myStrings contains "","Abc","Def","","Ghi","",""

Strings::iterator itNewBegin = myStrings.begin();
Strings::iterator itNewEnd = myStrings.end();

std::advance(itNewBegin,1);
std::advance(itNewEnd,4);

String myTrimmedStrings(itNewBegin,itNewEnd);
//... currently myTrimmedStringscontains "Abc","Def","","Ghi"

出于好奇,我希望看到你的代码使用反向迭代器。 我没有掌握从两个具有不同方向的迭代器构造新向量的方法。

答案 4 :(得分:0)

迭代器肯定是要走的路。它们使代码更具可读性和直观性。

#include <algorithm>

typedef std::vector<std::string> strVec_t;

bool notEmpty(std::string s){
  return !s.empty();
}

void trim(strVec_t& vec){

  //get the first and last non-empty elements
  strVec_t::const_iterator        first = std::find_if(vec.begin(),  vec.end(),  notEmpty);
  strVec_t::const_reverse_iterator last = std::find_if(vec.rbegin(), vec.rend(), notEmpty);

  //if every element is an empty string, delete them all
  if (first == vec.end()){
    vec.clear();

  //make a new vector from the first to the last non-empty elements
  } else {
    vec = strVec_t(first, last.base());
  }
}