我有两个迭代器,一个list和一个itertools.count对象(即无限值生成器).我想将这两个合并到一个生成的迭代器中,它将在两者之间交替屈服值:
>>> import itertools
>>> c = itertools.count(1)
>>> items = ['foo', 'bar']
>>> merged = imerge(items, c) # the mythical "imerge"
>>> merged.next()
'foo'
>>> merged.next()
1
>>> merged.next()
'bar'
>>> merged.next()
2
>>> merged.next()
Traceback (most recent call last):
...
StopIteration
Run Code Online (Sandbox Code Playgroud)
这样做最简单,最简洁的方法是什么?
我是C++的新手,所以请耐心等待.我想了解STL iterator_traits.在"C++标准库"一书中,iterator_traits结构定义如下:
template <class T>
struct iterator_traits{
typedef typename T::value_type value_type
typedef typename T::difference_type difference_type
typedef typename T::iterator_category iterator_category
typedef typename T::pointer pointer
typedef typename T::reference reference
}
Run Code Online (Sandbox Code Playgroud)
所以在我看来,它正在重新暴露T已经暴露的子类型.继续前进,本书给出了如何使用它的示例,如下所示
template <class MyIterator>
void do_something(MyIterator start, MyIterator end) {
typedef typename iterator_traits<MyIterator>::value_type value_type
value_type v = *start
.....
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么我在这里需要这个iterator_traits结构,如果想要获得它value_type,我不能MyIterator直接获得它吗?我的困惑似乎来自于我(肯定是不正确的)理解,即子类型的信息必须来源于template <class T>用于实例化iterator_trait.所以如果你能解释一下,最好用一个例子说明为什么以及在哪里我需要iterator_traits,这将是非常有帮助的.
只需一点介绍,简单的单词.在C++中,迭代器是"事物",你可以在其上至少编写解引用运算符*it,增量运算符++it,对于更高级的双向迭代器,减量--it,最后但并非最不重要的是,对于随机访问迭代器,我们需要运算符索引it[]和可能的加法和减法.
C++中的这类"东西"是具有相应运算符重载的类型的对象,或简单和简单的指针.
std::vector<>是一个包装连续数组的容器类,因此指针作为迭代器是有意义的.在网上,在一些文献中你可以找到vector.begin()用作指针.
使用指针的基本原理是开销更少,性能更高,特别是如果优化编译器检测到迭代并执行其操作(向量指令和内容).使用迭代器可能更难以使编译器进行优化.
知道这一点,我的问题是为什么现代STL实现,比如Mingw 4.7中的MSVC++ 2013或libstdc ++,为矢量迭代器使用了一个特殊的类?
它是有效的创建一个迭代end(str)+1的std::string?
如果不是,为什么不呢?
这个问题是限制在C++ 11以后,因为在预C++ 11中的数据已经存储在连续块中的任何但是罕见POC玩具的实现,该数据没有具有要被存储的方式.
而且我认为这可能会产生重大影响.
std::string我推测的任何其他标准容器之间的显着差异在于它总是包含一个元素size,而不是它的零终止符,以满足要求.c_str().
21.4.7.1 basic_string访问器[string.accessors]
Run Code Online (Sandbox Code Playgroud)const charT* c_str() const noexcept; const charT* data() const noexcept;1返回:一个指针
p,p + i == &operator[](i)用于每个iin[0,size()].
2复杂性:恒定时间.
3要求:程序不得更改存储在字符数组中的任何值.
尽管如此,尽管它应该保证所述表达式是有效的,但为了保持与零终止字符串的一致性和互操作性,如果没有别的话,我发现的唯一一段对此表示怀疑:
21.4.1 basic_string一般要求[string.require]
4对象中的类似char的
basic_string对象应连续存储.也就是说,任何basic_string对象s,身份&*(s.begin() + n) == &*s.begin() + n应持的所有值n这样0 <= n < s.size().
(所有引用均来自C++ 14最终草案(n3936).)
相关: …
假设我们有一个向量:
let a = vec![1, 2, 3];
Run Code Online (Sandbox Code Playgroud)
迭代元素的最佳和最短的方法是什么,以便在第一次迭代中我收到一个元组(1, 2),并在下一次迭代中收到 - (2, 3),直到没有元素,所以不会产生(3, None)或类似的东西?看起来a.chunks(2)有点不同,它以 2 为步长,而我需要在集合中的每两个连续元素上以 1 为步长。
使用迭代器可以提供什么(如果有的话)性能优势.它似乎是解决许多问题的"正确方法",但是它是否会创建更快/更具记忆意识的代码?我在Python中专门思考,但不限制答案.
在Java中:是否是List.iterator()线程安全的,即返回的迭代器是在任何时候反映列表的当前状态还是仅在列表创建时反映列表的状态?
请考虑以下代码.
std::vector<result_data> do_processing()
{
pqxx::result input_data = get_data_from_database();
return process_data(input_data);
}
std::vector<result_data> process_data(pqxx::result const & input_data)
{
std::vector<result_data> ret;
pqxx::result::const_iterator row;
for (row = input_data.begin(); row != inpupt_data.end(); ++row)
{
// somehow populate output vector
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
当我在考虑是否可以期待返回值优化(RVO)时,我发现Jerry Coffin的这个答案 [强调我的]:
至少IMO,这通常是一个糟糕的主意,但不是出于效率原因.这是一个糟糕的主意,因为有问题的函数通常应该写成通过迭代器生成输出的通用算法.几乎任何接受或返回容器而不是在迭代器上运行的代码都应该被认为是可疑的.
不要误解我的意思:有时候传递类似于集合的对象(例如字符串)是有意义的,但对于引用的例子,我会考虑传递或返回向量一个糟糕的想法.
有一些Python背景,我非常喜欢Generators.实际上,如果它是Python,我会把上面的函数写成一个Generator,即避免在其他任何事情发生之前处理整个数据的必要性.例如这样:
def process_data(input_data):
for item in input_data:
# somehow process items
yield result_data
Run Code Online (Sandbox Code Playgroud)
如果我正确地解释了Jerry Coffins的说法,这就是他的建议,不是吗?如果是这样,我如何在C++中实现它?
我有多个迭代器,它们根据一些排序标准以排序的方式返回项目.现在,我想将迭代器合并(多路复用)到一个组合迭代器中.我知道如何用Java风格,例如树形图,但我想知道是否有更多功能方法?我想尽可能地保留迭代器的懒惰.