【问题标题】:C++ equivalent of this Python code for dictionaries/lists?用于字典/列表的此 Python 代码的 C++ 等价物?
【发布时间】:2012-08-27 08:47:52
【问题描述】:

在我的 Python 代码中,我有一个问题需要在开始翻译成 c++ 之前加以澄清:如何制作正确的字典/列表,我可以在其中使用相当于“if var in _”的.

任意需要翻译的例子:

CONFIRMATION = ('yes', 'yeah', 'yep', 'yesh', 'sure', 'yeppers', 'yup')
DECLINATION = ('no', 'nope', 'too bad', 'nothing')

varResponse = str(input('yes or no question'))
if varResponse in CONFIRMATION: 
    doSomething()
elif varResponse in DECLINATION: 
    doSomethingElse()
else:
    doAnotherThing()

使用数组执行类似的任务相当容易,例如:

if (userDogName == name[0])
    execute something;

但我需要的是这样的:

if (userDogName is one of a population of dog names in a dictionary)
    execute something;

【问题讨论】:

  • 如果列表不是太大,你可以对数组进行线性搜索。
  • 我有一些相当大的列表,但我会考虑那些小的。大的我该怎么办?
  • 元素的顺序是否重要,你可以重复吗?

标签: c++ visual-studio-2010 windows-7 python-3.2


【解决方案1】:

您可以使用 STL 容器类set。它使用平衡二叉树:

#include <iostream>
#include <set>
#include <string>

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

  set.insert("yes");
  set.insert("yeah");

  iter = set.find("yess");

  if (iter != set.end( ))
  {
    std::cout << "Found:" << *iter;
  }
  else
  {
    std::cout << "Not found!";
  }

  return 0;
}

【讨论】:

  • 我喜欢这种方法,但是有问题;如果我说 25 个术语,我会怎么做?我肯定不会 set.insert("term") 25 次吗?
  • 在 C++11 中,您可以使用初始化列表。只需搜索std::initializer_list 即可了解此概念。在您的程序中,您只需编写:set&lt;string&gt; as = {"a", "A" ....
  • 在旧版本中,您将使用set 的构造函数,它获取两个指针并假定它们指向数组的开头和结尾,然后用于初始化您的集合。
  • 但是在现实世界的应用程序中,您可能不会对列表进行硬编码,而是从某种配置文件中读取它们?这是我使用insert 背后的想法。
【解决方案2】:

C++11 允许一种与 Python 代码非常相似的解决方案:

#include <iostream>
#include <set>
#include <string>

using namespace std;

set<string> CONFIRMATION = {"yes", "yeah", "yep", "yesh", "sure", "yeppers", "yup"};
set<string> DECLINATION = {"no", "nope", "too bad", "nothing"};

int main() {
  cout << "yes or no question";
  string varResponse;
  getline(cin, varResponse);
  if (CONFIRMATION.find(varResponse) != CONFIRMATION.end()) {
    doSomething();
  } else if (DECLINATION.find(varResponse) != DECLINATION.end()) {
    doSomethingElse();
  } else {
    doAnotherThing();
  }
}

【讨论】:

  • @Cheersandhth.-Alf:不,我只能访问 Clang。
【解决方案3】:

嗯,C++ 不太适合小型临时程序,因为它没有提供太多的基础结构。您打算在标准库之上创建自己的基础结构(例如,甚至只是简单的集合!)。或者使用一些 3rd 方库,即您的选择

因此,虽然 Python 附带了电池,但对于 C++,接受特定提供的电池没有很大压力(因为没有),但您至少必须选择电池。

对于基本代码,Python sn-p

CONFIRMATIONS = ("yes", "yeah", "yep", "yesh", "sure", "yeppers", "yup")
DECLINATIONS = ("no", "nope", "too bad", "nothing")

response = raw_input( "yes or no? " )
if response in CONFIRMATIONS:
    pass # doSomething()
elif response in DECLINATIONS:
    pass # doSomethingElse()
else:
    pass #doAnotherThing()

在 C++ 中可以看起来像这样:

typedef Set< wstring > Strings;

Strings const   confirmations   = temp( Strings() )
    << L"yes" << L"yeah" << L"yep" << L"yesh" << L"sure" << L"yeppers" << L"yup";
Strings const   declinations    = temp( Strings() )
    << L"no" << L"nope" << L"too bad" << L"nothing";

wstring const response = lineFromUser( L"yes or no? " );
if( isIn( confirmations, response ) )
{
    // doSomething()
}
else if( isIn( declinations, response ) )
{
    // doSomethingElse()
}
else
{
    // doAnotherThing()
}

但是,它依赖于已定义的一些基础结构,例如 Set 类:

template< class TpElem >
class Set
{
public:
    typedef TpElem      Elem;

private:
    set<Elem>   elems_;

public:
    Set& add( Elem const& e )
    {
        elems_.insert( e );
        return *this;
    }

    friend Set& operator<<( Set& s, Elem const& e )
    {
        return s.add( e );
    }

    bool contains( Elem const& e ) const
    {
        return (elems_.find( e ) != elems_.end());
    }
};

template< class Elem >
bool isIn( Set< Elem > const& s, Elem const& e )
{
    return s.contains( e );
}

我使用了operator&lt;&lt;,因为截至 2012 年,Visual C++ 不支持 C++11 花括号列表初始化。

这里的set 是标准库中的std::set

还有,嗯,temp 东西:

template< class T >
T& temp( T&& o ) { return o; }

还有更多的基础设施,lineFromUser 函数:

wstring lineFromUser( wstring const& prompt )
{
    wcout << prompt;

    wstring result;
    getline( wcin, result )
        || throwX( "lineFromUser: std::getline failed" );
    return result;
}

其中,依赖于 throwX 函数:

bool throwX( string const& s ) { throw runtime_error( s ); }

但仅此而已,除了您必须将我首先展示的 C++ 代码放入某个函数中,例如调用 cppMain,然后从您的 main 函数中调用它(甚至需要定义更多的基础结构!):

int main()
{
    try
    {
        cppMain();
        return EXIT_SUCCESS;
    }
    catch( exception const& x )
    {
        wcerr << "!" << x.what() << endl;
    }
    return EXIT_FAILURE;
}

所以,要在 C++ 中正确地做一些事情,有一些高昂的开销。

C++ 主要用于大型程序,而 Python(我经常使用)用于小型程序。

是的,我知道有些学生可能会或将会对这种说法做出反应,或者他们觉得说它对小程序没有好处是对 C++ 的诽谤(嘿,我一直在做这些!)和/或者说它对大型系统没有好处是对 Python 的诽谤(嘿,你没听说过 YouTube,你这个愚蠢的无能的人吗?),但是,事实就是这样。有时用锤子拧螺丝会更方便,所以有时我用 C++ 做一些小任务。但一般来说这是因为在手边的机器上安装 Python 太麻烦了,而且一般来说,要执行 X 任务,最好使用专为 X 类工作设计的工具。

【讨论】:

    【解决方案4】:

    这可以在任何标准模板库容器上使用std::find 来解决。

    std::vector<std::string> answers;
    std::string input;
    ...
    if(std::find(answers.begin(), answers.end(), input) != answers.end()) {
        /* input was found in answers */
    } else {
        /* input was not found in answers */
    }
    

    对于较大的列表,最好将列表存储在 std::set 对象中,正如 Tilo 建议的那样。 std::find 也一样。

    【讨论】:

      猜你喜欢
      • 2017-10-14
      • 2015-02-24
      • 2016-07-21
      • 1970-01-01
      • 1970-01-01
      • 2012-04-05
      • 1970-01-01
      • 2016-01-10
      • 1970-01-01
      相关资源
      最近更新 更多