【问题标题】:C++ Arrays manipulations (python-like operations)C++ 数组操作(类似 python 的操作)
【发布时间】:2011-01-31 05:37:40
【问题描述】:

我正在尝试以 python 的方式找出用于数组操作的最佳 C++ 库/包。基本上我需要这样的简单:

values  = numpy.array(inp.data)
idx1    = numpy.where(values > -2.14)
idx2    = numpy.where(values < 2.0)

res1 = (values[idx1] - diff1)/1000
res2 = (values[idx2] - diff2)*1000

在 python 中它只有 5 行,但我能想到的 C++ 中最简单的方法是相当多的嵌套循环。请指教..

基本上,我的问题是关于数组/向量操作,如数组乘法、索引操作等。在上面的示例中, res1 是一个数组,包含一组从值数组中过滤出来的元素以及随后应用的一些算术(所有选定元素的减法、乘法)。在这个 python 示例中,我没有复制 values 数组的元素,因为它在内存方面可能足够大,我只保留索引并希望能够对原始数组的一组选定元素运行算术运算.

【问题讨论】:

  • 请为我们这些不熟悉 numpy 的人解释一下 Python 代码的作用。
  • 刚刚用更详细的解释扩展了我的问题
  • 为了清楚起见,您不是在寻找 C++ 标准库中的解决方案(因为没有,就像 numpy 不是 Python 标准库的一部分),您正在寻找一个能够操作像 numpy 这样的数组的优秀 3rd 方数学库? (我不知道有一个,但我怀疑它是否会与所有声明等一样简洁。)

标签: c++ python arrays


【解决方案1】:

您根本不应该使用数组。请坐下来了解 std::vector 类以及迭代器和标准库算法。我强烈建议阅读本书The C++ Standard Library

【讨论】:

  • 发帖人所说的“数组”不一定是C数组,是一般概念。
  • @static_rtti C++ 中的术语数组具有特定的技术含义。
【解决方案2】:

你可以在 C++ 中实现类似的东西,但你不应该使用纯 C 数组。

我可以看到这项工作的最简单方法是使用 std::set 的浮点数(您的代码看起来假设数据按升序排序)。您也可以使用浮动的std::vector,但您必须自己进行排序,可能使用std::sort

在这种情况下,您的示例代码可能如下所示 - 该集合假定值是唯一的,如果不是,您可以改用 std::multiset

std::set<float> values(inp.data.begin(), inp.data.end());
std::set<float>::iterator idx1 = values.lower_bound(-2.14);
std::set<float>::iterator idx2 = values.upper_bound(2.0);

float res1 = (*idx1 - diff1) / 1000.0;
float res2 = (*idx2 - diff2) / 1000.0;

请注意,上述代码示例不是您的原始代码的 100% 转换 - lower_bound为您提供第一个等于或大于 -2.14 的元素。我也没有为失败添加任何检查代码 - 例如,如果 lower_boundupper_bound 找不到匹配的元素,它们将返回 values.end()

使用向量,这个例子看起来非常相似,只是多一行来对向量进行预排序:

std::vector<float> values(inp.data.begin(), inp.data.end());
std::sort(values.begin(), values.end();
std::vector<float>::iterator idx1 = std::lower_bound(values.begin(), values.end(), -2.14);
std::vector<float>::iterator idx2 = std::upper_bound(values.begin(), values.end(), 2.0);

float res1 = (*idx1 - diff1) / 1000.0;
float res2 = (*idx2 - diff2) / 1000.0;

【讨论】:

  • 这确实是一个很好的例子,但不是我想要的。基本上在我的python示例中 res1 也是一个数组,表达式是一个向量运算。这意味着在 C++ 中,我必须将整个事情放在 2 个循环中,例如 while(idx1 != values.end) { res1.push_back((*idx1 - diff1)/1000); }; while(idx2 != values.end) { res2.push_back((*idx2 - diff2)/1000); };
  • 啊,好的。我想如果我说 Python 会有所帮助:)。您可以使用 std::copy 之类的东西隐藏循环,并通过带有后插入器的仿函数复制它们,但这比其他任何东西都更能隐藏循环。
【解决方案3】:

我建议你检查算法头。 也不要使用数组,你有 std::vector 或 boost(即将成为 std)::array。

wikipedia article

Reference for all algorithms

【讨论】:

    【解决方案4】:

    如果我没记错的话,numpy 主要是用 C 语言编写的(带有 Python 包装器),因此您可以直接从 C++ 中轻松使用它。

    【讨论】:

      【解决方案5】:

      如果你结合std::vectorboost::lambda,你可以非常接近你的例子:

      #include <algorithm>
      #include <iostream>
      #include <vector>
      #include <boost/lambda/lambda.hpp>
      
      using boost::lambda::_1;
      
      int main() {
          float ary[10] = { -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 };
          std::vector<float> v(&ary[0], &ary[10]);
          std::vector<float>::iterator iter1, iter2;
      
          iter1 = std::find_if(v.begin(), v.end(), (_1 > -2.14));
          iter2 = std::find_if(v.begin(), v.end(), (_1 < 2.0));
      
          // output:
          //     iter1 = -2.000
          //     iter2 = 1.000
          std::cout
              << "iter1 = " << *iter1 << "\n"
              << "iter2 = " << *iter2 << "\n"
              << std::endl;
          return 0;
      }
      

      【讨论】:

      • 同上。第一部分工作正常,但是像 res_vector = (v[iter1] - fixed_value)*1000 这样的向量操作呢?
      • 只有当“非常接近”你的意思是“十倍详细”:)
      • @static_rtti:大部分冗长之处在于设置和打印。 python 示例省略了import numpy 并且不包括打印。但是,是的,包含显式类型和其他静态信息会更加冗长。 main 内部的核心处理几乎是一样的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-16
      • 1970-01-01
      • 2014-05-11
      • 1970-01-01
      • 2017-01-27
      相关资源
      最近更新 更多