【问题标题】:Generate the Cartesian Product of 2 vector<string>s In-Place?就地生成 2 个向量 <string> 的笛卡尔积?
【发布时间】:2015-05-07 03:28:34
【问题描述】:

如果我想得到这两个vector&lt;string&gt;s 的笛卡尔积:

vector<string> final{"a","b","c"};
vector<string> temp{"1","2"};

但我想将结果放在final 中,这样最终将包含:

a1
a2
b1
b2
c1
c2

我想在不创建临时数组的情况下执行此操作。是否有可能做到这一点?如果重要的话,final 的顺序并不重要。

【问题讨论】:

  • @FrédéricHamidi 笛卡尔积和拉链是不同的东西。
  • @T.C.,你说得对,不知道我在想什么。投票被撤回。
  • final修改到位之前将final复制到临时对象是不是太过分了?
  • @RSahu 这是我目前的解决方案,所以我可以维护我正在使用的产品,但我对此不满意。理想情况下,这个问题会给我一个解决方法。

标签: c++ string vector temporary cartesian-product


【解决方案1】:

你可以试试下面的方法

#include <iostream>
#include <vector>
#include <string>

int main() 
{
    std::vector<std::string> final{ "a", "b", "c" };
    std::vector<std::string> temp{ "1", "2" };

    auto n = final.size();

    final.resize( final.size() * temp.size() );

    for ( auto i = n, j = final.size(); i != 0; --i )
    {

        for ( auto it = temp.rbegin(); it != temp.rend(); ++it )
        {
            final[--j] = final[i-1] + *it; 
        }

    }

    for ( const auto &s : final ) std::cout << s << ' ';
    std::cout << std::endl;

    return 0;
}

程序输出是

a1 a2 b1 b2 c1 c2 

【讨论】:

  • 我认为我有一个比你更好的solution,因为它的分支更少(我想?)但是你的解决方案每次都更快,所以我接受了它。关于为什么你的更快的任何想法?分工真的那么慢吗?
  • @Jonathan Mee 我认为差异与冗余操作 % 和 /.
  • 我想这是有道理的。我曾期望编译器将它们剥离到一个操作中。可能不会。无论如何,很好的解决方案,谢谢。
【解决方案2】:

试试笛卡尔函数:

#include <vector>
#include <string>

using namespace std;

void cartesian(vector<string>& f, vector<string> &o) {
int oldfsize = f.size();
f.resize(oldfsize * o.size());
for (int i = o.size() - 1; i>=0; i--) {
  for (int j = 0; j < oldfsize; j++) {
     f[i*oldfsize + j] = f[j] + o[i];
  }
 }
}


int main() 
{
vector<string> f{"a","b","c"};
vector<string> temp{"1","2"};
cartesian(f, temp);
for (auto &s: f) {
  printf("%s\n", s.c_str());
 }
}

【讨论】:

  • 很酷! :) for (auto &s: f) { printf("%s\n", s.c_str()); }
  • 很高兴你喜欢它 ;) c++11 rulez ;)
【解决方案3】:

这对我有用:

void testCartesianString(vector<string>& final,
                         vector<string>const& temp)
{
   size_t size1 = final.size();
   size_t size2 = temp.size();

   // Step 1.
   // Transform final to : {"a","a","b","b","c","c"}
   final.resize(size1*size2);
   for ( size_t i = size1; i > 0; --i )
   {
      for ( size_t j = (i-1)*size2; j < i*size2; ++j )
      {
         final[j] = final[i-1];
      }
   }

   // Step 2.
   // Now fix the values and
   // change final to : {"a1","a2","b1","b2","c1","c2"}
   for ( size_t i = 0; i < size1; ++i )
   {
      for ( size_t j = 0; j < size2; ++j )
      {
         final[i*size2+j] = final[i*size2+j] + temp[j];
         cout << final[i*size2+j] << " ";
      }
      cout << endl;
   }
}

【讨论】:

  • 这也是我的第一种方法,但是如果您要花时间在单独的循环中进行初始化,您应该使用它。 final[i*size2+j] += temp[j]; 而不是 final[i*size2+j] = final[i*size2+j] + temp[j]; 无论如何我认为Vlad from Moscow 的解决方案有点优越,因为它只触及每个元素一次。
【解决方案4】:

这只是Vald from Moscow 解决方案的个人偏好选项。我认为动态数组可能会更快,因为分支会更少。但是我还没有开始编写时序测试台。

给定输入 vector&lt;string&gt; finalvector&lt;string&gt; temp

const auto size = testValues1.first.size();

testValues1.first.resize(size * testValues1.second.size());

for (int i = testValues1.first.size() - 1; i >= 0; --i){
    testValues1.first[i] = testValues1.first[i % size] + testValues1.second[i / size];
}

编辑:

不,这个解决方案更慢而不是更快:http://ideone.com/e.js/kVIttT

而且通常要快得多,虽然我不知道为什么......

无论如何,更喜欢Vlad from Moscow的回答

【讨论】:

    猜你喜欢
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 2015-04-16
    • 2021-05-06
    • 2021-09-05
    • 2017-06-02
    • 2015-06-03
    • 2016-05-07
    相关资源
    最近更新 更多