是否有一些STL函数可以获得两个C ++向量的笛卡尔积?

时间:2016-06-09 13:28:41

标签: c++ string vector stl

假设

b =  ["good ", "bad "]
a  = ["apple","mango"]
then output = ["good apple","good mango","bad apple","bad mango"]

我知道这可以通过嵌套for循环来完成,但是使用C ++ STL是否有一些优雅的衬里呢?

3 个答案:

答案 0 :(得分:4)

以下是单行(从Jonathan Mee's回复posted here复制):

for(size_t i = 0, s = a.size(); i < output.size(); ++i) output[i] = b[i/s] + ' ' + a[i%s];

完整示例here

答案 1 :(得分:3)

鉴于vector<string> avector<string> b,您可以使用for_each

vector<string> output(size(a) * size(b));

for_each(begin(output), end(output), [&, it = 0U](auto& i) mutable {
    i = a[it / size(b)] + ' ' + b[it % size(b)];
    ++it;
});

Live Example

修改

我们已初步确定output有足够的空间来包含ab的所有组合。然后我们将逐步浏览output的每个元素并分配它。

我们要使用a的1 st 元素作为size(b)的第一个output元素,以及2 nd < / sup> a元素,用于第二个size(b)元素,依此类推。因此,我们将通过使用it / size(b)建立索引来实现此目的。我们希望通过b的元素迭代来组合它。

it将转移到output的每个元素的下一个索引,但索引需要换行,或者it == size(b)时它将超出范围,为此我们使用it % size(b) 1}}。

<强> EDIT2:

this question通过基准测试,我发现了模数和除法是迭代的昂贵操作的现象。我在这里做了同样的测试。为了隔离算法,我只是在vector<int>而不是vector<string>上进行笛卡尔求和。

首先我们可以看到两种算法导致不同的装配。我上面写的算法需要585行汇编。我对MSalter's code

的解释需要588行
vector<string> output(size(testValues1) * size(testValues2));
auto i = begin(output);

std::for_each(cbegin(a), cend(a), [&](const auto& A) { std::for_each(cbegin(b), cend(b), [&](const auto& B) { *i++ = A + ' ' + B; }); });

我已经在这里进行了一个非常可靠的基准测试:http://ideone.com/1YpzIO在测试中我只设置了100个测试,但MSalters的算法总是获胜。本地使用Visual Studio 2015,发布时有10,000,000次测试,MSalters算法的完成时间约为我的时间的2/3。

显然,模数不是一种很好的索引方法:(

答案 2 :(得分:3)

没有直接的解决方案;我检查了整个<algorithm>。这些函数都没有产生长度为M * N的输出。

可以做的是在第一个范围内调用std::for_each,使用在第二个范围调用std::for_each的lambda(!)

std::vector<std::string> a, b;
std::for_each(a.begin(), a.end(), 
  [&](std::string A) { std::for_each(b.begin(), b.end(),
      [A](std::string B) { std::cout << A << '/' << B << '\n';  }
);});

但这只是STL中的嵌套循环。