将矢量<std::string>转换为矢量<double>
Convert vector<std::string> to vector<double>
我有一个类似{"1.2","3.4","0.5","200.7"}
的字符串向量。
我想将每个元素转换为double,并将其存储在vector<double>
中。
像这样{1.2,3.4,0.5,200.7}
最好的方法是什么?
我知道std::stod(string, size)
;但我希望有更好的方法来做到这一点。
我在找这样的东西:
vector<double> doubleVector = convertStringVectortoDoubleVector(myStringVector);
似乎没有这样的事情;那么接下来最好的事情是什么呢?
编辑:以下是我最终使用的:
std::vector<double> convertStringVectortoDoubleVector(const std::vector<std::string>& stringVector){
std::vector<double> doubleVector(stringVector.size());
std::transform(stringVector.begin(), stringVector.end(), doubleVector.begin(), [](const std::string& val)
{
return stod(val);
});
return doubleVector;}
要获得完整的答案,请查看扎克的答案和克里斯·杰斯特·杨的答案。(附言:这完全基于扎克的回答)感谢
为了完整性(因为Chris从他的回答中删除了编辑):
std::vector<double> doubleVector(stringVector.size());
std::transform(stringVector.begin(), stringVector.end(), doubleVector.begin(), [](const std::string& val)
{
return std::stod(val);
});
与使用std::back_inserter
而不使用reserve
的比较
在没有保留的情况下,每次back_inserter
调用push_back
时都要冒着调整阵列大小的风险。它必须根据当前容量检查当前大小,如果需要增加容量,它会将矢量复制到新位置(增加容量)。在所有这些之后,它将增加大小并插入新元素。当您知道要开始的大小(它将与stringVector
的大小相匹配)时,这是一个很大的开销。
使用std::back_inserter
和reserve
的比较
保留适当数量的内存可以防止重新分配问题,但push_back
仍然会更新大小,并检查每次迭代是否达到了容量。您已经大大减少了开销(不再因为大小问题而需要"移动"阵列的风险),但仍有许多不必要的条件检查。
最初设置大小时,将所有元素设置为默认值(在双精度的情况下为0.0)的开销很小。在每次迭代中,您只需设置当前元素的值。因此,对于一个由N个元素组成的向量,您有2N+2个赋值(设置容量、大小、元素的初始值和元素的实际值),没有不必要的条件检查。除了N个条件检查外,保留方法还有2N+1个分配(设置容量一次,更新大小N次,并设置N个加倍的值)。
如果你真的想进一步优化它,你可以创建自己的迭代器包装来进行转换,这样你就可以在初始化向量时为doubles写正确的值:
// pseudo-code
std::vector<double> doubleVector(my_string_conversion_iterator(stringVector.begin()), my_string_conversion_iterator(stringVector.end());
您应该使用std::transform
将转换应用于每个元素。
vector<double> doubleVector;
doubleVector.reserve(stringVector.size());
transform(stringVector.begin(), stringVector.end(), back_inserter(doubleVector),
[](string const& val) {return stod(val);});
正如Zac Howland所指出的,这里有另一种方法,它包括首先用默认构建的元素初始化向量,然后简单地用正确的值填充向量:
vector<double> doubleVector(stringVector.size());
transform(stringVector.begin(), stringVector.end(), doubleVector.begin(),
[](string const& val) {return stod(val);});
这种方法的优点是矢量只调整一次大小,而不是连续增长。缺点是必须首先默认构造向量元素,然后用正确的值重新分配。对于满足以下所有条件的元素类型,这种权衡是值得的:
- 可以默认构造
- 默认构造成本低廉
- 可以分配相同类型的值
- 分配起来很便宜
在这种情况下,double
满足所有四个要求,因此后一种方法更好。对于其他类型,尤其是在编写函数模板时,默认实现应该使用前一种方法。
使用std::transform
vector<string> str ;
vector<double> dv ;
std::transform(str.begin(), str.end(), back_inserter(dv), [](const string & astr){ return stod( astr) ; } ) ;
您可以在C++11中使用std:for_each
和lambda
。
vector<string> a = {"1.2","3.4","0.5","200.7"};
vector<double> b;
for_each(a.begin(), a.end(), [&b](const string &ele) { b.push_back(stod(ele)); });
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- ///<评论></评论>在Visual Studio中