标签: iterator

从顺序集合中获取随机元素

我谈到了一个API,它给了我java.util.Iterator一个集合.这意味着我可以迭代它,但我不能直接/随机访问元素.

现在我的问题:我想从这个集合中获得一个随机元素.我怎么做?我想我可以构建一个允许直接访问的新集合,但这不是一点消耗内存吗?我也可以迭代整个集合,并为每个元素"掷骰子",看看我是否应该采用该元素并退出迭代或继续.但后来我需要集合的大小,我无法从迭代器中获得.

提前致谢.

java iterator

10
推荐指数
2
解决办法
5570
查看次数

为什么不同的包中有Iterable <E>和Iterator <E>?

Iterable<E>是在,java.langIterator<E>java.util.这有充分的理由还是仅仅是一个糟糕设计的神器?

这似乎很奇怪,因为唯一Iterable<E>有益的是提供一个Iterator<E>.

编辑:一个潜在的原因是因为(then-)新引入的每个循环.我想我的问题是,它们是否相同?

for(Object o : collection)
    ...
vs
for( Iterator iter = collection.iterator(); iter.hasNext(); ) {
    o = iter.next();
    ...
Run Code Online (Sandbox Code Playgroud)

如果它们是,那么仍然无法解释为什么这两个类在不同的包中,因为编译器必须导入java.util才能使用该Iterator构造.

java iterator iterable

10
推荐指数
3
解决办法
5016
查看次数

有比较两个迭代器的内置方法吗?

我编写了以下函数来比较两个迭代器,逐个元素.但是,如果我可以在标准库中重用某些东西,那就太好了.

fn iter_eq<A, B, T, U>(mut a: A, mut b: B) -> bool
where
    A: Iterator<Item = T>,
    B: Iterator<Item = U>,
    T: PartialEq<U>,
{
    loop {
        match (a.next(), b.next()) {
            (Some(ref a), Some(ref b)) if a == b => continue,
            (None, None) => return true,
            _ => return false,
        }
    }
}

fn main() {
    let a = vec![1, 2, 3].into_iter();
    let b = vec![1, 2, 3].into_iter();

    assert!(iter_eq(a, b));
}
Run Code Online (Sandbox Code Playgroud)

iterator rust

10
推荐指数
2
解决办法
1929
查看次数

C++中基于接口的编程与迭代器的结合.怎么这么简单?

在我的开发中,我正在慢慢地从面向对象的方法转向基于接口的编程方法.更确切地说:

  • 在过去,如果我能在课堂上分组逻辑,我已经满意了
  • 现在我倾向于在界面后面添加更多逻辑并让工厂创建实现

一个简单的例子澄清了这一点.

过去我写过这些课程:

  • 图书馆

现在我写这些类:

  • ILibrary
  • 图书馆
  • LibraryFactory
  • 我订了
  • BookFactory

这种方法允许我轻松地为每个接口实现模拟类,并在旧的,较慢的实现和新的,更快的实现之间切换,并在同一个应用程序中进行比较.

对于大多数情况,这非常好,但如果我想使用迭代器来循环集合,它就会成为一个问题.

假设我的图书馆有一系列书籍,我想对它们进行迭代.在过去,这不是问题:Library :: begin()和Library :: end()返回一个迭代器(Library :: iterator),我可以在其上轻松编写循环,如下所示:

for (Library::iterator it=myLibrary.begin();it!=mylibrary.end();++it) ...
Run Code Online (Sandbox Code Playgroud)

问题是在基于接口的方法中,不能保证ILibrary的不同实现使用相同类型的迭代器.如果例如OldLibrary和NewLibrary都继承自ILibrary,那么:

  • OldLibrary可以使用std :: vector来存储它的书籍,并在其开始和结束方法中返回std :: vector :: const_iterator
  • NewLibrary可以使用std :: list来存储它的书籍,并在其开始和结束方法中返回std :: list :: const_iterator

要求两个ILibrary实现都返回相同类型的迭代器也不是解决方案,因为在实践中,增量操作(++ it)需要在两个实现中以不同方式实现.

这意味着在实践中我必须使迭代器成为一个接口,这意味着应用程序不能将迭代器放在堆栈上(典型的C++切片问题).

我可以通过在非接口类中包装iterator接口来解决这个问题,但对于我尝试obtian的东西,这似乎是一个非常复杂的解决方案.

有没有更好的方法来处理这个问题?

编辑: 马丁发表评论后的一些澄清.

假设我有一个类,它返回按受欢迎程度排序的所有书籍:LibraryBookFinder.它有begin()和end()方法,它们返回一个引用书籍的LibraryBookFinder :: const_iterator.

要用一个全新的实现替换旧的实现,我想将旧的LibraryBookFinder放在ILibraryBookFinder接口后面,并将旧实现重命名为OldSlowLibraryBookFinder.

然后我的名为VeryFastCachingLibraryBookFinder的新(快速快速)实现可以继承ILibraryBookFinder.这是迭代器问题的来源.

下一步可能是隐藏工厂后面的界面,在那里我可以要求工厂"给我一个'发现者'非常擅长根据人气,或根据标题,或作者,...返回书籍.你最终得到了像这样的代码:

ILibraryBookFinder *myFinder = LibraryBookFinderFactory (FINDER_POPULARITY);
for (ILibraryBookFinder::const_iterator it=myFinder->begin();it!=myFinder.end();++it) ...
Run Code Online (Sandbox Code Playgroud)

或者如果我想使用其他标准:

ILibraryBookFinder *myFinder = LibraryBookFinderFactory (FINDER_AUTHOR);
for (ILibraryBookFinder::const_iterator it=myFinder->begin();it!=myFinder.end();++it) ...
Run Code Online (Sandbox Code Playgroud)

LibraryBookFinderFactory的参数可以由外部因素决定:配置设置,命令行选项,对话框中的选择,......每个实现都有自己的优化(例如,书籍的作者不会改变)所以这可以是一个非常静态的缓存;流行度可以每天改变,这可能意味着完全不同的数据结构).

c++ iterator design-patterns interface

9
推荐指数
1
解决办法
1840
查看次数

C++ OutputIterator后增量要求

C++要求OutputIterator类型X支持表单的表达式r++,其中r是一个实例X.此后缀增量必须在语义上等效于:

(*) { X tmp = r; ++r; return tmp; }

并且必须返回可转换为的类型X const&.在C++ 11中,请参见24.2.4(但这不是新的).它说,在同一部分

输出迭代器上的算法绝不应该尝试两次通过相同的迭代器.它们应该是单通道算法.

给出(*),上面说我复制返回值就像 X a(r++);

  1. 假设r在递增之前是dereferencable,但没有取消引用.它是否需要a被取消参考?如果是这样,必须X a(r++); *a = t;执行相同的任务*r++ = t;吗?是否有任何(其他)条件ar

  2. 否则,假设r在递增之前被解除引用/分配,并且其递增的值(也)是不可引用的.以下哪一项(如果有的话)定义明确:(a) *a = t;,(b)++a; *a = t;,(c)*r = t;


另请参阅后续操作:取消引用 - 分配给双倍增量的OutputIterator

c++ iterator post-increment

9
推荐指数
1
解决办法
652
查看次数

循环特征矩阵的最有效方法

我正在创建一些函数来做一些事情,比如负数和正数的分离和,kahan,成对和其他东西,其中我从矩阵中获取元素的顺序无关紧要,例如:

template <typename T, int R, int C>
inline T sum(const Eigen::Matrix<T,R,C>& xs)
{
  T sumP(0);
  T sumN(0);
  for (size_t i = 0, nRows = xs.rows(), nCols = xs.cols(); i < nRows; ++i)
   for (size_t j = 0; j < nCols; ++j)
   {
        if (xs(i,j)>0)
          sumP += xs(i,j);
        else if (xs(i,j)<0) //ignore 0 elements: improvement for sparse matrices I think
          sumN += xs(i,j);
   }
 return sumP+sumN;
}
Run Code Online (Sandbox Code Playgroud)

现在,我想尽可能提高效率,所以我的问题是,如上所述循环遍历每一行的每一列会更好,或者像下面这样做相反:

for (size_t i = 0, nRows = xs.rows(), nCols = xs.cols(); i …
Run Code Online (Sandbox Code Playgroud)

c++ performance iterator eigen

9
推荐指数
2
解决办法
2万
查看次数

有没有办法使用独立的`std :: begin`和const_iterator?

我喜欢一致性.我最近问过使用std::begin与例如的问题std::vector<int>::begin,并且一致的决定似乎是使用前者,因为它更通用.但我想我在泥里找到了一根棍子.有时候,你想传达的是,当你循环通过时,你不会改变容器,因此调用std::vector<int>::cbegin.它将使你有时做你的代码很不对称iter = v.cbegin()等次做iter = begin(v).有没有办法解决这种缺乏对称性的问题,你还会推荐std::begin这种知识吗?为什么C++没有std::cbegin

c++ iterator const-correctness c++11

9
推荐指数
1
解决办法
1608
查看次数

如何对ReadDir迭代器进行排序

我可以显示如下目录列表:

use std::fs;

fn main() {
    let paths = fs::read_dir("./").unwrap();
    for path in paths {
        println!("Name: {}", path.unwrap().path().display())
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以在ReadDir迭代之前对迭代器进行排序吗?目录名称是类似日期的数字201610131503.我阅读了文档,ReadDir但是没有找到内置函数.也许我不知道如何搜索?

iterator rust

9
推荐指数
2
解决办法
1244
查看次数

std :: move()是否使迭代器无效?

考虑以下程序:

struct list_wrapper
{
    std::vector<int>    m_list;
};

int main()
{
    std::vector<int> myList { 1, 1, 2, 3, 5 };

    const std::vector<int>::iterator iter = myList.begin();

    list_wrapper wrappedList;
    wrappedList.m_list = std::move(myList);

    // Can I still dereference iter?

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在调用之后std::move(myList),iter现在指向内部的有效项wrappedList.m_list,或者移动构造函数/赋值使所有迭代器无效?

c++ iterator undefined-behavior move-semantics c++11

9
推荐指数
2
解决办法
1201
查看次数

使用索引与迭代器迭代向量到倒数第二个元素

当从C++ 11的开头迭代std::vector到第二个到最后一个元素时,首选的样式是什么?

std::vector<const char*> argv;
std::string str;
Run Code Online (Sandbox Code Playgroud)

应该使用这种更多的C++ - esque方法

for (const auto& s: decltype(argv)(argv.begin(), argv.end()-1)) {
    str += std::string(s) + ' ';
}
Run Code Online (Sandbox Code Playgroud)

还是应该采用更传统的方式?

for (size_t i = 0; i < argv.size() - 1; ++i) {
    str += std::string(argv[i]);
}
Run Code Online (Sandbox Code Playgroud)

c++ iterator vector std c++11

9
推荐指数
2
解决办法
499
查看次数