标签: iterator

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
查看次数

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

我正在创建一些函数来做一些事情,比如负数和正数的分离和,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万
查看次数

在相同的输入迭代器范围内并排运行两个<algorithm>

如果我想计算从a中检索到的一堆数字的总和std::istream,我可以执行以下操作:

// std::istream & is = ...
int total = std::accumulate(std::istream_iterator<int>(is),
                            std::istream_iterator<int>(),
                            0);
Run Code Online (Sandbox Code Playgroud)

但是,如果我想计算它们的平均值,我需要累积两个不同的结果:

  • 总和(std::accumulate)
  • 总数(std::distance)

有没有办法"合并"这两种算法并在迭代器范围的单次传递中"并排"运行它们?我想做的事情如下:

using std::placeholders;
int total, count;
std::tie(total, count) = merge_somehow(std::istream_iterator<int>(is),
                                       std::istream_iterator<int>(),
                                       std::bind(std::accumulate, _1, _2, 0),
                                       std::distance);
double average = (double)total / count;
Run Code Online (Sandbox Code Playgroud)

这可能吗?

c++ algorithm iterator istream-iterator stl-algorithm

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

故障安全迭代器的逻辑是什么?

如果故障安全迭代器创建一个单独的副本并对其进行处理,那么它如何知道对原始文件所做的任何更改?

public class concurrentHashMap {
    public static void main(String[] args) throws InterruptedException {
        MapCheck obj1 = new MapCheck();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                obj1.put();
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                obj1.iterte();
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

class MapCheck {
    Map<Integer,String> map = new ConcurrentHashMap<>();
    {
        map.put(1, "pujan");
        map.put(2, "manish");
        map.put(3, "swati");
    }

    void iterte() throws InterruptedException {
        for (int key : map.keySet()) …
Run Code Online (Sandbox Code Playgroud)

java collections iterator

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

迭代pyspark数据框列

我有以下几点pyspark.dataframe

age  state  name    income
21    DC    john    30-50K
NaN   VA    gerry   20-30K
Run Code Online (Sandbox Code Playgroud)

我试图实现相当于df.isnull().sum()(来自熊猫)产生:

age      1
state    0
name     0
income   0
Run Code Online (Sandbox Code Playgroud)

起初我尝试了一些类似的东西:

null_counter = [df[c].isNotNull().count() for c in df.columns]
Run Code Online (Sandbox Code Playgroud)

但这会产生以下错误:

TypeError: Column is not iterable
Run Code Online (Sandbox Code Playgroud)

同样,这就是我目前迭代列以获得最小值的方式:

class BaseAnalyzer:
    def __init__(self, report, struct):
        self.report = report
        self._struct = struct
        self.name = struct.name
        self.data_type = struct.dataType
        self.min = None
        self.max = None

    def __repr__(self):
        return '<Column: %s>' % self.name


class BaseReport:
    def __init__(self, df):
        self.df = df …
Run Code Online (Sandbox Code Playgroud)

python iterator pyspark pyspark-sql

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

使用 Dart 有条件地返回 Map() 中的元素

假设我有一个可迭代对象(可以是映射(键)、列表、集合等),并且希望使用 Map() 将其转换为具有函数 f 的另一个可迭代对象。然而,我希望 f 在转换后仅在满足条件时返回一个值。

List<int> a = [1,2,3,4,5,6];
List<int> b = a.map((e) => (e % 2 == 0) ? e * 10 : null);

assert(b == [20,40,60]);
Run Code Online (Sandbox Code Playgroud)

然而,这会返回一个错误,就像map中带有mapEntry的任何类似的等效项一样,例如:

Map<int, String> a = {1:a, 2:b, 3:c, 4:d, 5:e, 6:f};
Map<int, String> b = a.map((k,v) => (k % 2 == 0) ? MapEntry(k*10,v) : null);

assert(b.keys.toList<int>() == [20,40,60]);
Run Code Online (Sandbox Code Playgroud)

当然,有一些方法可以通过牺牲效率和简洁性来解决这个问题,即在映射值之前或之后循环遍历它以过滤掉不需要的值。例如:

List<int> b = a.where((e) => e%2).map((e) => e * 10);
List<int> b = a.map((e) => e * 10).where((e) => e%2); …
Run Code Online (Sandbox Code Playgroud)

dictionary iterator arraylist filter dart

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

What is the best way to dereference values within chains of iterators?

当我使用迭代器时,我经常发现自己需要显式取消引用值。以下代码查找向量中所有元素对的总和:

extern crate itertools;

use crate::itertools::Itertools;

fn main() {
    let x: Vec<i32> = (1..4).collect();

    x.iter()
        .combinations(2)
        .map(|xi| xi.iter().map(|bar| **bar)
        .sum::<i32>())
        .for_each(|bar| println!("{:?}", bar));
}
Run Code Online (Sandbox Code Playgroud)

有没有比使用 a 更好的执行解除引用的方法map

更好的是无需显式取消引用即可执行这些类型的操作。

iterator rust

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

如何包装 std::vector 以在纯 C 中使用

在我的项目中,我想使用 C++ 和 STL 容器,但有一个问题,我必须包含用 ANSI C 编写的包含 C++ 的硬件供应商标头(并链接供应商库并使用一些还包括供应商标头的供应商 C 源)保留关键字,例如:vendor.h:

// Vendor header (read only)
    struct Vendor_Export_Struct {
    unsigned char* data;
};

struct Vendor_Export_Struct export; // <<<  compilation error under C++
union Vendor_Union {
    struct Vendor_Export_Struct export; // <<<  compilation error under C++
};
Run Code Online (Sandbox Code Playgroud)

包含在 C++ 中的内容将在编译期间导致错误:在“导出”之前预期不合格的 id。所以我被迫使用纯 C 并考虑是否可以简单地将 STL 向量包装成这样的 C API(后面有 C++ 实现):

cvect.h :

typedef void* Vect_Type;
typedef void** Vect_Iterator_Type;
typedef void* Vect_Data_Type;

Vect_Type Vect_New();
void Vect_PushBack(Vect_Type v, Vect_Data_Type d);
Vect_Iterator_Type Vect_Begin(Vect_Type v);
Vect_Iterator_Type …
Run Code Online (Sandbox Code Playgroud)

c c++ iterator stdvector

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

如何迭代多个不同长度的列表,但重复较短列表的最后一个值,直到完成最长列表?

在我的 Python 3 脚本中,我试图根据输入组合来自三个不同列表的三个数字。如果列表大小相同,则zip. 但是,我希望能够为特定列表输入单个数字,并且脚本可以重复该数字,直到最长的列表完成。这可以通过zip_longest. 但是,fillvalue对于单独的列表,不可能有单独的填充值。

以这个简单的脚本为例:

from itertools import zip_longest

list1=[1]
list2=[4, 5, 6, 7, 8, 9]
list3=[2]
for l1, l2, l3 in zip_longest(list1, list2, list3):
     print(l1, l2, l3)
Run Code Online (Sandbox Code Playgroud)

这是实际结果:

# 1    4 2
# None 5 None                                                        
# None 6 None                                                         
# None 7 None
# None 8 None
# None 9 None  
Run Code Online (Sandbox Code Playgroud)

这将是我想要的结果:

# 1 4 2
# 1 5 2                                                        
# 1 6 2                                                         
# 1 7 2
# 1 …
Run Code Online (Sandbox Code Playgroud)

python iterator list python-3.x

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

如果不推荐使用 std::iterator ,我们还应该使用需要 std::iterator 的类或函数吗?

我听说std::iterator在 C++17 中不推荐使用。

例如,像功能<algorithm>,更可能我们要使用begin()end()它返回迭代器对象,如成员函数std::stringstd::vector等等。

或者像基于范围的 for 循环,我们需要的地方begin()以及end()返回迭代器的地方。

因此,如果std::iterator基类被弃用,我们是否应该使用成员函数,如begin()end()或使用 STL 中需要迭代器的其他函数?

c++ iterator for-loop c++17

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