我可以在这里摆脱嵌套的循环吗?

Can I get rid of nested for loops here?

本文关键字:循环 嵌套 在这里 我可以      更新时间:2023-10-16

我有一个函数,它接受一个向量,并通过组合其中的所有元素来返回一个向量。现在,我有 3 个嵌套的循环,可以创建一个 3 级深的组合。我希望它看起来更好,并且能够在需要时添加功能以使其深度为 4 级。

如果输入 = ["一"、"二"、"三"]

3级输出="一二三"二一三"等。

std::vector<std::string> generator(std::vector<std::string>& x)
{
    std::vector<std::string> output;
    std::string tmp;
    for (auto i : x) {
        output.push_back(i);
        for (auto j : x) {
            tmp = i + j;
            output.push_back(tmp);
            for (auto k : x) {
                tmp = i + j + k;
                output.push_back(tmp);
            }
        }
    }
    return output;
}

我已经研究了迭代器,但我无法弄清楚它是否有效。

如果您正在寻找的是简单地生成字符串向量x的所有元素的排列,并将这些排列存储到另一个输出向量中,这可以通过使用 std::next_permutation 和 std::accumulate 轻松实现:

#include <vector>
#include <string>
#include <numeric>
#include <iostream>
#include <algorithm>
std::vector<std::string> generator(std::vector<std::string> x)
{
    std::vector<std::string> output;
    std::sort(x.begin(), x.end());
    do 
    {
        output.push_back(std::accumulate(x.begin(), x.end(), std::string()));
    } while (std::next_permutation(x.begin(), x.end()));
    return output;
}
int main()
{
    auto v = generator({"one","two","three"});
    for (auto& val : v)
        std::cout << val << "n";
}    

现场示例

默认情况下,std::accumulate基本上对元素调用operator +,因此字符串会自动连接。

std::next_permutation而言,链接中解释了它的功能。 基本上,您希望从排序序列开始,并调用std::next_permutation以获取元素的下一个排列。

请注意,这并不取决于"级别"的数量(正如您所说的那样)。 你可以有一个 10 个字符串的向量,这将正常工作(假设没有内存限制)。

如果你想生成最大长度为 L 的 N 个单词的所有组合,你可以使用这个:

std::vector<std::string> generator(const std::vector<std::string> & x, int levels) {
    int nWords = x.size();
    std::vector<std::string> output;
    for (int l = 1; l <= levels; ++l) {
        int nCombs = std::pow(nWords, l); 
        for (int i = 0; i < nCombs; ++i) {
            std::string cur;
            for (int j = 0, k = i; j < l; ++j) {
                cur += x[k%nWords];
                k /= nWords;
            }
            output.push_back(cur);
        }
    }
    return output;
}

现场示例

仍然有 3 个嵌套循环,但这适用于 L 的任何值 - 而不仅仅是 3。L> N 也有效。

嗨,

我曾经在 Python 中遇到过类似的问题。

我想的目标是有一个"n嵌套"循环,这样n就是一个变量。更好的结果是使级别i的每个索引I_i都是变量。也就是说,给定一个列表[I_1,I_2,...,I_n],你应该能够生成这样的循环

for i_1 in range( I_1):
    for i_2 in range( I_2):
       ...
          for i_n in range(I_n):
             some_function(i_1,i_2,...,i_n)

一种方法是使用数学。您可以构建一个数字,以便在第 i 位数字上,它是基于I_i的。这个数字的最大值只是 I_1*I_2*...*I_n .这样,整个循环将被折叠成一个简单的循环

for i in range(I_1*I_2*...*I_n):
    # obtain these numbers
    i_1 = f_1(i)
    i_2 = f_2(i)
    ...
    i_n = f_n(i)
    some_function(i_1,i_2,...,i_n)

虽然获取i的功能有点复杂。

正如您所提到的,另一种方法是迭代器。在Python中,它只是import itertools。然而,在C++,我发现了这个cppitertools。我还没有尝试过,但我想这可以工作。

不过,如果你想要速度,第一个方法更受欢迎。不过,我认为有更好的解决方案。