【问题标题】:Efficient way of creating an array/vector of strings and finding out the length of all strings in it创建字符串数组/向量并找出其中所有字符串长度的有效方法
【发布时间】:2020-07-12 11:02:59
【问题描述】:

我想创建一个函数,我可以在其中迭代包含可变数量字符串的数组/向量,并且在将字符串发送到函数之前我需要知道字符串的长度。我怎样才能以有效的方式实现这一目标?

我对该函数有一些松散的想法,但是我如何有效地向它发送一个字符串数组/向量以及所有这些字符串的大小组合。例如,函数可能如下所示:

myFunc(vector<string> s, int totalWordLength) {
    // Loop over strings in vector.
}

我可以做这样的事情来创建一个字符串向量。

const char *args[] = {"12345", "678"};
vector<string> s(args, end(args));

但是我如何在不循环的情况下找出其中字符串 (8) 的大小,以便我可以将其发送到 myFunc(s, sizeOfStrings)

如果您想通过使用数组或其他方式来实现相同的结果,请告诉我。我正在尝试尽可能高效地做到这一点。

【问题讨论】:

  • 在收到字符串时将它们的长度相加,或者遍历向量并将它们的 size() 相加。
  • “没有循环通过它”约束使它变得困难。即使auto total = accumulate(s.begin(), s.end(), 0UL, [](auto acc, string a) { return acc + a.length(); }); 内部也有一个循环,除非您忽略了代表您循环的算法。

标签: c++ arrays string performance vector


【解决方案1】:

遍历容器(容器类无关)

const char *args[] = {"12345", "678"};
vector<string> s(args, end(args));

size_t sizOfS = 0;
for( auto& item : s )
  sizOfS += item.length();

另一种方法是统一填充数组和计算长度的过程:

const char *args[] = {"12345", "678"};
std::vector<std::string> s;
s.reserve(sizeof(args)/sizeof(args[0]));

size_t sizOfS = 0;
for( const std::string& item : args )
{
  sizOfS += item.length();
  s.push_back(item);
}

无论您做什么,该过程的成本都是 O(n),其中n = strings * their-total-length。没有其他定义的方式,但有几个函数可以将循环变成单线。即使定义自己的容器来跟踪字符串的长度,它的成本也会有相同的顺序。

使用哪个容器取决于您希望执行什么样的操作,vector 随机访问容器项目的成本是恒定的,但增加其存储的成本会线性增加。 list 可能有便宜的插入\推送成本,但它有顺序迭代器。

【讨论】:

    【解决方案2】:

    如果您想知道向量中所有字符串的长度并经常查询它(这不是一次性的事情),那么您可以在将字符串加在一起时计算字符串的长度并将总和存储为向量。

    一个简单的例子:

    class MyClassFoo {
    public:
      std::vector<std::string> items;
      std::size_t total_item_sizes = 0;
    
      void addItem(const std::string& item) {
        total_item_sizes += item.length(); // Add its length to the total
        items.emplace_back(item); // Add the item to the vector 
      }
    }
    

    然后你可以传递这个对象并查询它。

    如果您想更有效地通过引用传递或移动一次性使用参数。这对于 std::vector 之类的东西很重要,因为您可能不想复制它的所有元素。

    顺便说一句,这不太可能实际上 neccasary,除非您尝试非常频繁地对所有字符串的长度求和并且有很多字符串,否则您的瓶颈将不会重复一个std::vector。您对“效率”的需求听起来像是过早的优化。记住 20-80 规则(80% 的程序执行时间用于运行 20% 的代码)。

    【讨论】:

      【解决方案3】:

      根据您的情况,一种方法可能是在构造向量时计算字符串的长度。

      使用可变参数模板的一种解决方案可能是这样的包装器 (live):

      #include <iostream>
      #include <vector>
      #include <string>
      
      struct V
      {
          template <typename ... T>
          V( T&& ... t ) : v{ std::forward<T>(t)... }
          {
              for ( const auto& s : v ) size += s.size();
          }
      
          std::vector<std::string> v;
          std::size_t size {0};
      };
      
      int main()
      {
          const char *args[] = { "12345678", "6789", "1234", "5678" };
      
          V obj ( std::begin(args), std::end(args) );
      
          std::cout << "No. of Strings : " << obj.v.size() << '\n';
          std::cout << "Total Length   : " << obj.size << '\n';
      
          return 0;
      }
      

      输出:

      No. of Strings : 4
      Total Length   : 20
      

      【讨论】:

        猜你喜欢
        • 2020-12-10
        • 2019-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-16
        • 1970-01-01
        相关资源
        最近更新 更多