用c ++交叉产品

Wil*_*ris 3 c++ python

给出以下Python(来自http://norvig.com/sudoku.html)

def cross(A, B):
    "Cross product of elements in A and elements in B."
    return [a+b for a in A for b in B]

cols     = '123456789'
rows     = 'ABCDEFGHI'
squares  = cross(rows, cols)
Run Code Online (Sandbox Code Playgroud)

这会产生:

['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'B1', 'B2', 'B3', ...]
Run Code Online (Sandbox Code Playgroud)

作为练习,我想在C++中做同样的事情.目前我有:

#include <iostream>
#include <map>
#include <vector>

using std::string;
using std::vector;

static vector<string> cross_string(const string &A, const string &B)
{
    vector<string> result;

    for (string::const_iterator itA = A.begin(); itA != A.end(); ++itA) {
        for (string::const_iterator itB = B.begin(); itB != B.end(); ++itB) {
            char s[] = {*itA, *itB, 0};
            result.push_back(string(s));
        }
    }
    return result;
}

int main(int argc, char** argv)
{
    const char digits[] = "123456789";
    const char rows[]   = "ABCDEFGHI";

    vector<string> res = cross_string(rows, digits);

    for (vector<string>::const_iterator it = res.begin();
         it != res.end(); ++it) {
        std::cout << *it << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

这有效,但我希望有更好的方法.这也只做字符串,而python做任何列表......


编辑:

感谢所有的回复.我接受了我最了解的那个,但Alf的答案紧随其后.我注意到所有使用C++ 11并且想知道作为C++的新手我是否应该直接采用它而不是学习旧标准.但这可能是另一个问题的最佳选择.

Che*_*Alf 5

那么只是提供代码而不是解释:

#include <iostream>         // std::wcout, std::endl
#include <string>           // std::string
#include <utility>          // std::begin, std::end
#include <vector>
using namespace std;

string sum( char const a, char const b ) { return string() + a + b; }

template< class Container >
auto cross( Container const& a, Container const& b )
    -> vector< decltype( sum( *begin( a ), *begin( b ) ) ) >
{
    typedef decltype( sum( *begin( a ), *begin( b ) ) ) ResultItem;
    vector< ResultItem >   result;

    for( auto&& itemA : a ) for( auto&& itemB : b )
    {
        result.push_back( sum( itemA, itemB ) );
    }
    return result;
}

wostream& operator<<( wostream& stream, string const& s )
{
    return (stream << s.c_str());
}

template< class Item >
wostream& operator<<( wostream& stream, vector<Item> const& v )
{
    stream << "[";
    bool isFirstItem = true;
    for( auto&& item : v )
    { 
        if( !isFirstItem ) { stream << ", "; }
        stream << item;
        isFirstItem = false;
    }
    stream << "]";
    return stream;
}

int main()
{
    string const cols       = "123456789";
    string const rows       = "ABCDEFGHI";
    auto const squares      = cross( cols, rows );

    wcout << squares << endl;
}
Run Code Online (Sandbox Code Playgroud)


Kon*_*lph 5

奇怪的cross_product是,C++ 算法库中缺少它。它可以轻松添加,但正如 Jerry 和 Alf 的回答所示,关于如何做到最好的意见不同。事实上,我仍然会做不同的事情。Jerry 的接口符合其他 C++ 算法的接口,但他没有抽象出叉积运算,我会这样做:

template <typename InputIt1,
          typename InputIt2,
          typename OutputIt,
          typename F>
void cross_product(InputIt1 begin1,
                   InputIt1 end1,
                   InputIt2 begin2,
                   InputIt2 end2,
                   OutputIt out,
                   F f) {
    for (auto i = begin1; i != end1; ++i)
        for (auto j = begin2; j != end2; ++j)
            *out++ = f(*i, *j);
}
Run Code Online (Sandbox Code Playgroud)

在您的示例中,调用将如下所示:

auto digits = "1234546789";
auto chars = "ABCDEFGHI";
vector<string> result;

cross_product(digits, digits + strlen(digits),
              chars, chars + strlen(chars),
              back_inserter(result),
              [](char a, char b) { return string() + a + b; });
Run Code Online (Sandbox Code Playgroud)

(我不就是喜欢 C++11 吗?是的,我喜欢。)

在一个合适的库中,我会提供第二个重载,它提供一个默认f操作,该操作创建一个类似于 Jerry 代码所做的元组。甚至可以进一步抽象以允许两个以上的范围——毕竟,Python 列表推导式允许您迭代两个以上的范围)。