Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对集合进行排序<;字符串>;以长度为基础_C++_Stl_Lambda_C++11_Set - Fatal编程技术网

C++ 对集合进行排序<;字符串>;以长度为基础

C++ 对集合进行排序<;字符串>;以长度为基础,c++,stl,lambda,c++11,set,C++,Stl,Lambda,C++11,Set,我的问题是关于 我想在lambda表达式作为谓词的帮助下,对集合执行sort()操作 我的代码是 #include <set> #include <string> #include <iostream> #include <algorithm> int main() { using namespace std; string s = "abc"; set<string> results; do { for (in

我的问题是关于

我想在lambda表达式作为谓词的帮助下,对
集合执行
sort()
操作

我的代码是

#include <set>
#include <string>
#include <iostream>
#include <algorithm>
int main() {
  using namespace std;
  string s = "abc";
  set<string> results;
  do {
    for (int n = 1; n <= s.size(); ++n) {
      results.insert(s.substr(0, n));
    }
  } while (next_permutation(s.begin(), s.end()));

  sort (results.begin(),results.end());[](string a, string b)->bool{

              size_t alength = a.length();
              size_t blength = b.length();
              return (alength < blength);
  });
  for (set<string>::const_iterator x = results.begin(); x != results.end(); ++x) {
    cout << *x << '\n';
  }
  return 0;
}
#包括
#包括
#包括
#包括
int main(){
使用名称空间std;
字符串s=“abc”;
设定结果;
做{
对于(int n=1;n布尔){
尺寸长度=a.长度();
尺寸?混合度=b.长度();
返回值(alength集合中的排列是固定的,因此唯一可以使用的迭代器是
const
迭代器

您需要先将
结果
复制到
向量
deque
(或类似)中


不能对集合进行排序。集合总是按键排序(键本身就是元素)


更具体地说,
std::sort
需要随机访问迭代器。
std::set
提供的迭代器不是随机的。

需要
set
不提供的随机访问迭代器(它是一个双向迭代器)。如果您将代码更改为使用
vector
,它将编译得很好。

您可以通过提供自定义谓词来自定义
集中元素的顺序,以确定添加元素相对于现有成员的顺序。
定义为

template <
    class Key, 
    class Traits=less<Key>, 
    class Allocator=allocator<Key> 
>
class set
模板<
类密钥,
阶级特征=更少,
类分配器=分配器
>
类集
特质在哪里

提供函数的类型 对象,该对象可以比较两个元素 值作为排序键,以确定其 集合中的相对顺序。此 参数是可选的,二进制 谓词less是默认值 价值观

这是有背景的

在您的情况下,这意味着:

auto comp = [](const string& a, const string& b) -> bool 
    { return a.length() < b.length(); };
auto results = std::set <string, decltype(comp)> (comp);
auto comp=[](常量字符串和a、常量字符串和b)->bool
{返回a.length()
请注意,这将导致具有相同字符串长度的
set
元素被视为重复的元素,就我所能理解的预期结果而言,这不是您想要的。

Edit:请注意,这实际上就是您正在搜索的元素,因为他以C++0x Lambda的形式内联了我在下面编写的C++03代码

另一个解决方案是定制
std::set
排序函数:

struct MyStringLengthCompare
{
    bool operator () (const std::string & p_lhs, const std::string & p_rhs)
    {
        const size_t lhsLength = p_lhs.length() ;
        const size_t rhsLength = p_rhs.length() ;

        if(lhsLength == rhsLength)
        {
            return (p_lhs < p_rhs) ; // when two strings have the same
                                     // length, defaults to the normal
                                     // string comparison
        }

        return (lhsLength < rhsLength) ; // compares with the length
    }
} ;
std::set
已订购。。。
std::set
有它自己的顺序,一旦构建了它,就不应该更改它。因此,下面的代码:

int main(int argc, char* argv[])
{
    std::set<std::string> aSet ;

    aSet.insert("aaaaa") ;
    aSet.insert("bbbbb") ;
    aSet.insert("ccccccc") ;
    aSet.insert("ddddddd") ;
    aSet.insert("e") ;
    aSet.insert("f") ;

    outputSet(aSet) ;

    return 0 ;
}
…但您可以自定义其排序功能 现在,如果需要,您可以使用自己的比较功能自定义设置:

struct MyStringLengthCompare
{
    bool operator () (const std::string & p_lhs, const std::string & p_rhs)
    {
        const size_t lhsLength = p_lhs.length() ;
        const size_t rhsLength = p_rhs.length() ;

        if(lhsLength == rhsLength)
        {
            return (p_lhs < p_rhs) ; // when two strings have the same
                                     // length, defaults to the normal
                                     // string comparison
        }

        return (lhsLength < rhsLength) ; // compares with the length
    }
} ;
集合现在将使用functor
MyStringLengthCompare
对其项目进行排序,因此,此代码将输出:

 - e
 - f
 - aaaaa
 - bbbbb
 - ccccccc
 - ddddddd
但要小心订购错误! 创建自己的排序函数时,必须遵循以下规则:

如果(lhs
如果由于某种原因,您的排序函数不尊重它,您的手上就会有一个损坏的集合。

std::set对于维护排序和变异列表非常有用。当集合本身在构建后不会发生太大变化时,使用向量会更快、更小

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
int main() {
  using namespace std;
  string s = "abc";
  vector<string> results;
  do {
    for (size_t n = 1; n <= s.size(); ++n) {
      results.push_back(s.substr(0, n));
    }
  } while (next_permutation(s.begin(), s.end()));

  //make it unique
  sort( results.begin(), results.end() );
  auto end_sorted = unique( results.begin(), results.end() );
  results.erase( end_sorted, results.end() );

  //sort by length
  sort (results.begin(),results.end());
          [](string lhs, string rhs)->bool
             { return lhs.length() < rhs.length(); } );

  for ( const auto& result: results ) {
    cout << result << '\n';
  }
}
#包括
#包括
#包括
#包括
int main(){
使用名称空间std;
字符串s=“abc”;
矢量结果;
做{
对于(尺寸n=1;n布尔)
{返回lhs.length()cout既然我编写了您正在使用的原始代码,也许我可以对其进行扩展…:)

struct cmp\u按长度{
模板
布尔运算符()(T常量和a、T常量和b){
返回a.length()
这将首先按长度进行比较,然后按值进行比较。修改集合定义:

set<string, cmp_by_length> results;
设置结果;
你可以走了:

int main() {
  using namespace std;
  string s = "abc";
  typedef set<string, cmp_by_length> Results;  // convenience for below
  Results results;
  do {
    for (int n = 1; n <= s.size(); ++n) {
      results.insert(s.substr(0, n));
    }
  } while (next_permutation(s.begin(), s.end()));

  // would need to add cmp_by_length below, if I hadn't changed to the typedef
  // i.e. set<string, cmp_by_length>::const_iterator
  // but, once you start using nested types on a template, a typedef is smart
  for (Results::const_iterator x = results.begin(); x != results.end(); ++x) {
    cout << *x << '\n';
  }

  // of course, I'd rather write... ;)
  //for (auto const &x : results) {
  //  cout << x << '\n';
  //}

  return 0;
}
intmain(){
使用名称空间std;
字符串s=“abc”;
typedef set Results;//为下文提供方便
结果;
做{

对于(int n=1;n我想问他为什么首先要将它们插入一个集合。@ybung:我想是为了删除重复项。其他人已经注意到不能对一个std::集合进行std::排序。此外,我认为
);
就在lambda表达式应该是逗号之前。这会改变程序的行为。现在,集合只能包含一个任意给定长度的字符串,而不是任意给定值。您的输出有错误;要获得该结果,需要
multiset
@Potatoswatter:问题作者的程序将忽略带有dif的字符串不同的内容,但长度相同。但作者没有描述程序的意图。只是它被窃听了。我猜原始程序的行为是错误的。这就是为什么我自己的比较函数处理“相同长度,不同内容”的情况。我将在我的回答中澄清这一点,其有趣的价值不在于比较函数的确切代码,而在于它的使用及其陷阱。@Potatoswatter:现在,如果你遵循链接,你会看到作者希望能够对相同长度的字符串进行排列,如“abc”、“bca”等。“仅长度”在这种情况下,比较功能对他没有帮助。这让我相信我在提供“长度和内容”时是正确的比较。@Potatoswatter:最后,但并非最不重要的一点,我想知道你的评论是否暗示我的代码和/或其输出是错误的。因此,为了澄清一切,我的代码在发布之前已经过测试,其输出是真实的。所以我的“输出没有错误”。啊,现在我看到了“默认到正常比较”case.+1.@Roger-由于包含代码,您的注释被篡改了,我想-我的答案已经表明它将导致字符串w的dup
struct cmp_by_length {
  template<class T>
  bool operator()(T const &a, T const &b) {
    return a.length() < b.length() or (a.length() == b.length() and a < b);
  }
};
set<string, cmp_by_length> results;
int main() {
  using namespace std;
  string s = "abc";
  typedef set<string, cmp_by_length> Results;  // convenience for below
  Results results;
  do {
    for (int n = 1; n <= s.size(); ++n) {
      results.insert(s.substr(0, n));
    }
  } while (next_permutation(s.begin(), s.end()));

  // would need to add cmp_by_length below, if I hadn't changed to the typedef
  // i.e. set<string, cmp_by_length>::const_iterator
  // but, once you start using nested types on a template, a typedef is smart
  for (Results::const_iterator x = results.begin(); x != results.end(); ++x) {
    cout << *x << '\n';
  }

  // of course, I'd rather write... ;)
  //for (auto const &x : results) {
  //  cout << x << '\n';
  //}

  return 0;
}