用C ++ 17的功能方式做笛卡尔积

问题描述

我正在尝试使用闭包/自定义函数来实现笛卡尔乘积,闭包为function(x,y) = pow(x,2) + pow(y,2)并以函数方式实现,即不使用C样式循环。

这是我的主意。

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
void print (vector<int> aux) {
  vector<int>::iterator it = aux.begin();
  while(it != aux.end()){
    cout << *it << " ";
    it++; }}

int main() {
  vector<int> a{1,2};
  vector<int> b{3,4};
  vector<int> cartesian(4);
  transform (a.begin(),a.end(),b.begin(),cartesian.begin(),[](int &i)
         {vector<int>::iterator p = b.begin();
           for_each(begin(b),end(b),[](int &n) { return pow(i,2) + pow(n,2) })});
  print(cartesian);
  // desired output is: 10,17,13,20 (cartesian operation)
}

首先,使用第一个向量的每个元素,迭代第二个向量,然后将应用函数的结果存储在结果向量中。

代码仅用于表示目的。它不会编译。除其他外,它会导致'b' is not captured in {vector<int>::iterator p = b.begin();错误

如何纠正此代码和/或如何正确地使用闭包实现笛卡尔运算?

解决方法

您的编译问题是因为您没有在lambda中捕获所需的变量,并且缺少了一些;

但是,制作笛卡尔乘积的一种简单方法是使用2个嵌套循环,如下所示:

for (int i : a)
  for (int j : b)
    cartesian.push_back(i * i + j * j);

如果要使用算法,则可以编写:

for_each(begin(a),end(a),[&](int i) { 
  for_each(begin(b),end(b),[&](int j) { 
    cartesian.push_back(i * i + j * j); 
  });
});

尽管我觉得这很难阅读,并且并没有太大帮助,因为for_each是一种恰好具有内置语言结构的算法,类似于transform


从c ++ 20开始,添加了范围和视图,因此您可以发挥更大的创造力:

namespace rs = std::ranges;
namespace rv = std::views;

auto product = [=](int i) 
{
   auto  op = [=](int j) { return i * i + j * j;};

   return b | rv::transform(op);
};
  
rs::copy(a | rv::transform(product) 
           | rv::join,std::back_inserter(cartesian));

同样,原始的嵌套for循环可能是笛卡尔乘积的最佳方法,但这应该使您领会令人兴奋的可能性。

这里是demo

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...