zoukankan      html  css  js  c++  java
  • Matlab迭代器模式

    迭代器(Iterator)模式,又叫做游标(Cursor)模式。提供一种方法访问一个容器(container)或者聚集(Aggregator)对象中各个元素,而又不需暴露该对象的内部细节。在采用不同的方式迭代时,只需要替换相应Iterator类即可。本文采用Matlab语言实现对元胞数组和string数组的遍历。

    Aggregator.m

    classdef Aggregator < handle
        methods(Abstract)
            iterObj = createIterator(~);
        end
    end
    

    CellAggregator.m

    classdef CellAggregator < Aggregator
        properties
            cell
        end   
        methods
            function obj = CellAggregator(cell)
                obj.cell = cell;
            end       
            function iterObj = createIterator(obj)
                iterObj = CellIterator(obj);
            end
        end
    end

    StringAggregator.m

    classdef StringAggregator < Aggregator
        properties
            string_arr
        end   
        methods
            function obj = StringAggregator(string_arr)
                obj.string_arr = string_arr;
            end       
            function iterObj = createIterator(obj)
                iterObj = StringIterator(obj);
            end
        end
    end

    Iterator.m

    classdef Iterator < handle
        methods(Abstract)
            hasNext(~);
            next(~);
        end
    end

    CellIterator.m

    classdef CellIterator < Iterator
        properties
            index = 1;
            aggHandle;
        end
        methods
            function obj = CellIterator(agg)
                obj.aggHandle = agg;
            end
            function res = hasNext(obj)
                if(obj.index <= length(obj.aggHandle.cell))
                    res = true;
                else
                    res = false;
                end
            end
            function ele = next(obj)
                if(obj.hasNext())
                    ele = obj.aggHandle.cell{obj.index};
                    obj.index = obj.index + 1;
                else
                    ele = [];
                end
            end
        end
    end

    StringIterator.m

    classdef StringIterator < Iterator
        properties
            index = 1;
            aggHandle;
        end
        methods
            function obj = StringIterator(agg)
                obj.aggHandle = agg;
            end
            function res = hasNext(obj)
                if(obj.index <= obj.aggHandle.string_arr.length)
                    res = true;
                else
                    res = false;
                end
            end
            function ele = next(obj)
                if(obj.hasNext())
                    ele = obj.aggHandle.string_arr(obj.index);
                    obj.index = obj.index + 1;
                else
                    ele = string.empty();
                end
            end
        end
    end
    

     测试代码:

    cell = CellAggregator({'matlab','cell','iter'});
    iterObj = cell.createIterator();
    while iterObj.hasNext()
        disp(iterObj.next());
    end
     
    str_arr = StringAggregator(["matlab","string","iter"]);
    iterObj = str_arr.createIterator();
    while iterObj.hasNext()
        disp(iterObj.next());
    end
    

    迭代器模式不仅可以对集合进行顺序遍历,而且可以以用户想要的条件进行遍历,如果想要统计列表中所有偶数的和,可以写成循环语句,如下所示:

    test_for.m

    list = [13,8,17,11,8,19,18,12,13,12];
    
    sum = 0;
    for i=1:length(list)
        if mod(list(i),2) == 0
            sum = sum + list(i);
        end
    end
    
    disp("列表中所有偶数的和:" + sum);
    
    sum = 0;
    for i=1:length(list)
        if mod(list(i),2) == 1
            sum = sum + list(i);
        end
    end
    
    disp("列表中所有奇数的和:" + sum);
    

    如果要统计列表中所有奇数的和,这就需要对循环语句块进行修改,如上所示。这就违反了对修改关闭的原则。而迭代器模式可以将循环语句块和业务语句块(sum求和)分离出去,这就需要对Aggregator和Iterator类进行继承,如下所示:

    ListAggregator.m

    classdef ListAggregator < Aggregator
        properties(Constant)
            EVEN_ITER = 0
            ODD_ITER = 1
        end
        properties
            list
        end   
        methods
            function obj = ListAggregator(list)
                obj.list = list;
            end       
            function iterObj = createIterator(obj,type_iter)
                if(type_iter == ListAggregator.EVEN_ITER)
                    iterObj = EvenIterator(obj);
                else
                    iterObj = OddIterator(obj);
                end
            end
        end
    end
    

    OddIterator.m

    classdef OddIterator < Iterator
        properties
            index = 1;
            aggHandle;
        end
        methods
            function obj = OddIterator(agg)
                obj.aggHandle = agg;
            end
            function res = hasNext(obj)
                res = false;
                while(obj.index <= length(obj.aggHandle.list))
                    if mod(obj.aggHandle.list(obj.index),2) == 1
                        res = true;
                        break;
                    end
                    obj.index = obj.index + 1;
                end
            end
            function ele = next(obj)
                if(obj.hasNext())
                    ele = obj.aggHandle.list(obj.index);
                    obj.index = obj.index + 1;
                else
                    ele = [];
                end
            end
        end
    end
    

    EvenIterator.m

    classdef EvenIterator < Iterator
        properties
            index = 1;
            aggHandle;
        end
        methods
            function obj = EvenIterator(agg)
                obj.aggHandle = agg;
            end
            function res = hasNext(obj)
                res = false;
                while(obj.index <= length(obj.aggHandle.list))
                    if mod(obj.aggHandle.list(obj.index),2) == 0
                        res = true;
                        break;
                    end
                    obj.index = obj.index + 1;
                end
            end
            function ele = next(obj)
                if(obj.hasNext())
                    ele = obj.aggHandle.list(obj.index);
                    obj.index = obj.index + 1;
                else
                    ele = [];
                end
            end
        end
    end
    

    test_iter.m

    list_agg = ListAggregator([13,8,17,11,8,19,18,12,13,12]);
    iterObj = list_agg.createIterator(ListAggregator.EVEN_ITER);
    sum = 0;
    while iterObj.hasNext()
        sum = sum + iterObj.next();
    end
    disp("列表中所有偶数的和:" + sum);
    
    iterObj = list_agg.createIterator(ListAggregator.ODD_ITER);
    sum = 0;
    while iterObj.hasNext()
        sum = sum + iterObj.next();
    end
    disp("列表中所有奇数的和:" + sum);
    

    如果需要返回列表标,可以将next函数的返回值定义成[ele,index] = next(obj),python里面有yield关键字,可以让迭代器模式更加简洁,见参考资料。

    迭代器模式还可以扁平化多层嵌套循环,如果找到所有水仙花数,可以使用三层循环,代码如下:

    test_for.m

    a = 1:9;
    b = 0:9;
    c = 0:9;
     
    for i=1:length(a)
        for j = 1:length(b)
            for k = 1:length(c)
                num = a(i)*100 + b(j)*10 + c(k);
                if a(i)^3 + b(j)^3 + c(k)^3 == a(i)*100 + b(j)*10 + c(k)
                    disp("" + num + "是水仙花数");
                end
            end
        end
    end
    

    如果使用迭代器模式来简化三层循环,只需要对Aggregator和Iterator类进行继承,代码如下:

    MutiListAggregator.m

    classdef MutiListAggregator < Aggregator
        properties
            lists
        end   
        methods
            function obj = MutiListAggregator(varargin)
                obj.lists = varargin;
            end       
            function iterObj = createIterator(obj)
                iterObj = MutiListIterator(obj);
            end
        end
    end
    

    MutiListIterator.m

    classdef MutiListIterator < Iterator
        properties
            indexs = [];
            lengths = [];
            aggHandle;
        end
        methods
            function obj = MutiListIterator(agg)
                obj.aggHandle = agg;
                for i= 1:length(obj.aggHandle.lists)
                    obj.lengths(i) = length(obj.aggHandle.lists{i});
                end
                obj.indexs = ones(1,length(obj.aggHandle.lists));
            end
            function res = hasNext(obj)
                if(obj.indexs(1) > obj.lengths(1))
                    res = false;
                else
                    res = true;
                end
            end
            function varargout = next(obj)
                if(obj.hasNext())
                    for i = 1:length(obj.aggHandle.lists)
                        temp_list = obj.aggHandle.lists{i};
                        varargout{i} = temp_list(obj.indexs(i));
                    end
                    obj.indexs(length(obj.aggHandle.lists)) = obj.indexs(length(obj.aggHandle.lists)) + 1;
                    for i = length(obj.aggHandle.lists):-1:2
                        if(obj.indexs(i) > obj.lengths(i))
                            obj.indexs(i) = mod(obj.indexs(i), obj.lengths(i));
                            obj.indexs(i - 1) = obj.indexs(i - 1) + 1;
                        end
                    end
                else
                    for i = 1:length(obj.aggHandle.lists)
                        varargout{i} = [];
                    end
                end
            end
        end
    end
    

    test_iter.m 

    list_agg = MutiListAggregator(1:9,0:9,0:9);
    iterObj = list_agg.createIterator();
    while iterObj.hasNext()
        [a,b,c] = iterObj.next();
        num = a * 100 + b * 10 + c;
        if a^3 + b^3 + c^3 == a * 100 + b * 10 + c
            disp("" + num + "是水仙花数");
        end
    end

    参考资料:

    https://mp.weixin.qq.com/s/tghaVkTPUijBJO0qxSXdZQ

  • 相关阅读:
    新加的keyword编码错误
    Robot framework模拟打开浏览器问题
    Chrome无法登陆
    Android App用MulticastSocket监听组播,为什么连接到不同路由、在不同手机上跑,有的能收到有的收不到
    ubuntu 14.04/15.10 安装基于eclipse的android app开发环境
    ubuntu15.10英文系统中文输入法配置 fcitx
    Amazon S3 上传文件 SSL23_GET_SERVER_HELLO握手错误
    Google Map API v2 番外篇 关于gps位置偏差及修正方法探讨
    Google Map API v2 (四)----- 导航路径
    Google Map API v2 (三)----- 地图上添加标记(Marker),标记info窗口,即指定经纬度获取地址字符串
  • 原文地址:https://www.cnblogs.com/usaddew/p/10909438.html
Copyright © 2011-2022 走看看