【问题标题】:what is the best C++ alternative to python dictionary and zip?python字典和zip的最佳C++替代品是什么?
【发布时间】:2014-11-03 19:20:14
【问题描述】:

python 中 dict(zip(values...)) 的最佳 C++ 替代方案是什么?

我正在辅导一个 C++ 学生,目前在我的课余时间,在我的工作中遇到了一段 Python 代码,发现我不知道最好的答案。

代码如下(我改了变量的名字,概括了一下,但思路是一样的):

(dict(zip(wordCollection, [word.strip() for word in currentLine.split(',')][1:-1])))

我已经使用 boost 将剥离和拆分的单词替换为修剪后的标记化向量,效果很好;但是,当我试图决定翻译 dict/zip 组合的最佳方式时,我不知所措。

【问题讨论】:

    标签: python c++ dictionary zipper


    【解决方案1】:

    一旦你有你的向量,比如:

    std::vector<std::string> wordCollection;
    std::vector<std::string> splitWords;
    

    然后你可以迭代:

    std::map<std::string, std::string> dict; // or std::unordered_map
    std::size_t minSize = std::min(wordCollection.size(), splitWords.size());
    for (size_t i = 0; i != minSize; ++i) {
        dict.insert(std::make_pair(wordCollection[i], splitWords[i]));
    }
    

    【讨论】:

      【解决方案2】:

      您真的不应该尝试将习语直接从一种语言翻译成另一种语言。

      在 C++ 中,您通常不会编写带有迭代器并生成新迭代器的函数;相反,您编写的函数接受输入和输出迭代器并从一个迭代器复制到另一个。因此,您可以编写一个zip 函数,它采用T 上的输入迭代器、U 上的输入迭代器和pair&lt;T, U&gt; 上的输出迭代器。

      但是您不会以这种方式将两个调用链接在一起,因为您的zip 函数不会返回任何可以有效传递给@987654326 的任何内容(如迭代器范围) @ 功能。相反,您可以创建一个 dict 模拟(unordered_map),在其中创建一个输出迭代器,然后使用 zip 函数将对复制到其中。

      类似这样的:

      template <I1, I2, O>
      void zip(I1 it1, I1 it1end, I2 it2, I2 it2end, O o) {
          while ((it1 != it1end) && (it2 != it2end)) {
              *o++ = std::make_pair(*it1++, *it2++);
          }
      }
      
      std::unordered_map<T, U> mapping;
      zip(c1.begin(), c1.end(), c2.begin(), c2.end(), std::inserter(mapping, mapping.end()));
      

      除了我认为您实际上不能以这种方式在unordered_map 上使用inserter,因此您必须改为编写map_inserter 函数。

      如果您在本地不知道 TU 类型,您可能希望将这一切包装在一个函数模板中,该模板从迭代器的元素类型中提取类型,以便您可以 auto 它. (在C++11中,你可以decltype它而不需要函数,但是表达式会很乱。)


      如果您对zipmap_inserter 有多种用途,则可能值得编写它们。但除此之外,更好的解决方案是将其扩展为显式循环:

      auto it1 = c1.begin(), it1end = c1.end(), it2 = c2.begin(), it2end = c2.end();
      std::unordered_map<T, U> mapping;
      while ((it1 != it1end) && (it2 != it2end)) {
          mapping[*it1++] = *it2++;
      }
      

      【讨论】:

      • 是的,我通常不会在实践中直接这样做,我也非常相信不要直接翻译成语;我只是好奇解决同一问题的最佳和正确的“C++ 方式”是什么
      • 我会以非常不同的方式编写 zip。我希望它像容器一样,这样用法就可以像for (auto pr : zip(c1, c2)) { ... }。我认为这比 OutputIterator 风格的算法更有用。
      • @Barry:我同意这样的东西更有用,但它们并不真正符合 STL 算法的习语。 (顺便说一句,我并不是在为 STL 算法习语辩护。我喜欢它,直到我发现了其他语言中的惰性列表和 Python 生成器之类的东西,并注意到在值得写的时候,而不是每隔一段时间就可以使用这些算法很多脚手架,你可以一直使用它们……这就是我不像以前那样使用 C++ 的原因之一。
      • @abarnert 这不是 c++ 所宣扬的趋势,恰恰相反,看看像 Sean Parent 这样优秀的 c++ 编码人员如何宣扬永远不要忘记标准库及其他库中的算法,我有一个完全不同的看法.
      【解决方案3】:

      IMO,dict 的最佳 C++ 替代方案是 std::unordered_map,它是一个哈希表,对于 zip,它是来自 D4128 ranges proposalranges::view::zip,可以通过 github.com/ericniebler/range-v3 访问其参考实现.

      C++11 代码:

      #include <string>
      #include <vector>
      #include <unordered_map>
      #include <range/v3/view/zip.hpp>
      
      int main() {
          using namespace std;
          using ranges::view::zip;
      
          int ints[] = {1, 2, 3};
          vector<string> strings = {"a", "b"};
          unordered_map<int, string> dict(zip(ints, strings));
      }
      

      我希望它在未来成为 C++ 标准。

      【讨论】:

        【解决方案4】:
        dict(zip(labels,values))  --->  dict([("a",1),("b",0)]) ---> dict(a=1,b=0)
        

        字典只是一个哈希表...这只是制作标签和值的哈希表,其中标签(或键)是wordCollection,标记化的字符串是值

        所以可能是一个哈希表......虽然在 c++ 中可能需要多行来完成它

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-09-18
          • 1970-01-01
          • 2010-09-12
          • 2014-01-15
          • 2011-02-19
          • 1970-01-01
          • 2019-05-29
          • 2011-01-12
          相关资源
          最近更新 更多