zoukankan      html  css  js  c++  java
  • 集合,没那么简单

    集合,没那么简单

             好久都没有碰过前端页面的东西了,前几天做一个下拉列表的动态增删,是由js在前台操作select的option来实现的,但是奇怪的事,有的时候不能正确的清空列表的所有选项!本来觉得没有什么可以记的,但是细细咀嚼,还是有必要的!

             先贴出我实现清空列表的代码  

    //删除列表的所有选项
    function clearListBox(listBox) {
        for (var i = 0; i < listBox.length; i++) {
            removeListBoxOption(listBox,i);
        };
    };

    //删除给定列表的某个选项
    function removeListBoxOption(listBox,index) {
        listBox.remove(index);
    };

             如果你没有一眼看出问题所在,那么我想你可能是foreach的忠实粉丝;其实集合也好,数组也罢,虽然很多时候是作为容器来使用,其实他们没有那么简单;

    很多时候他们是我们缓存昂贵资源的法宝,如果你对性能要求比较高,那么很多时候你的开发生活不能缺少它!

    从数据结构的角度来看,集合可以实现各种复杂的数据结构,.net中实现的字典、列表等等,都是基于数组实现的;同时不同的数据结构,自然遍历和增删的性能是不一样的,不过我们不用担心,这些微软的类库开发人员都为我们考虑了!不得不说微软为了提高开发人员的工作效率,替我们做了很多的工作;那能不能说,缺少数据结构和算法的web开发程序猿,就不是真正的程序员呢?这个留待以后谈;

    从更广义上来说,变量是承载某种类型数值的集合,原始类型的变量直接承载原始类型的内容;复合类型变量本质上承载各种原始类型的变量的集合,当然其也可以有复合类型的成员,当然类除了定义其数据,也定义了其行为来操作修改这些数据;还有我们平时使用的数据库二维关系表……

             以上纯属自己开发中的一些体会,有什么不对的地方,欢迎大家批评斧正;今天我们要解决的问题是列表集合的遍历删除问题;那么我们先来看看集合的遍历中一些容易被忽略的细节;

             Foreach的遍历,对获取集合的方法只会调用一次

            

    View Code
    public class Test
    {
        //集合字段
        private IList<int> collection = new List<int>() { 123456 };

        //集合字段对应属性
        public IList<int> Collection
        {
            get
            {
                Console.WriteLine("获取了集合");
                return this.collection;
            }
        }

        /// <summary>
        
    /// 测试foreach
        
    /// </summary>
        public void TestForeach()
        {
            foreach (int item in this.Collection)
            {
                int a = item;
            }
        }
    }

             For的正向遍历,每次我们都需要都会调用获取集合的方法,并且每次都要访问集合的长度

            

    View Code
    public class Test
    {
        //集合字段
        private IList<int> collection = new List<int>() { 123456 };

        //集合字段对应属性
        public IList<int> Collection
        {
            get
            {
                Console.WriteLine("获取了集合");
                return this.collection;
            }
        }

        /// <summary>
        
    /// for正向遍历集合
        
    /// </summary>
        public void TestForForward()
        {
            for (int i = 0; i < this.Collection.Count; i++)
            {
                int a = this.Collection[i];
            }
        }
    }

             For的反向遍历,只有第一次遍历的时候调用获取集合的方法               

    View Code
    public class Test
    {
        //集合字段
        private IList<int> collection = new List<int>() { 123456 };

        //集合字段对应属性
        public IList<int> Collection
        {
            get
            {
                Console.WriteLine("获取了集合");
                return this.collection;
            }
        }

        /// <summary>
        
    /// for反向遍历集合
        
    /// </summary>
        public void TestForReverse()
        {
            for (int i = this.Collection.Count - 1; i > -1; i--)
            {
                int a = this.Collection[i];
            }
        }
    }

             虽然这些细节会影响集合遍历的性能,但是这些并不是今天我们要关注的;在.net里他们的性能差异怎么样,js中差别怎么样,如果您感兴趣可以自己测试;

             Foreach的最终的实现是通过链表实现的,我想着也就是为什么我们遍历集合的时候,不能对其进行删除的原因吧!使用for遍历,我们是通过数组下表直接访问,我们可以在遍历的时候删除元素,但是每次删除元素后,集合的length就会变化;

             现在回过头来看看删除列表选项的代码,显然其问题就在每次遍历都要重新获取集合的length;那么我们可以这样修改

             For

    View Code 
    //使用for实现删除列表的所有选项
    function clearListBox(listBox) {
        for (var i = 0; i < listBox.length; ) {
            removeListBoxOption(listBox,i);
        };

             While

     

    View Code
    //while实现删除列表的所有选项
    function clearListBox(listBox) {
        while (listBox.length > -1) {
            removeListBoxOption(listBox,0);
        };
    };

     

             现在我们解决了删除列表的所有选项!好像没有什么问题了,那么现在我们需要将源列表中一些选项移动到目的列表中,这个时候我们怎么做呢?这个时候我们需要一个集合

    View Code 

     由于我们的功能实现的比较复杂,同时涉及的数据量比较大,同时提供可以搜索列表框中的选项,同时涉及到多个列表并且他们之间是有关联关系的,所以我自己实现了一个简单的字典集合,其功能主要是缓存列表数据源,并没有优化实现遍历的算法,黏贴部分代码,感兴趣可以看一下
    View Code 
    <script type="text/javascript" src="Scripts/jquery-1.4.1.js"></script>
    <script type="text/javascript">
        //源列表初始化字符串
        var initStr = "1,北京~2,上海~3,天津~4,河北~5,山东~6,河南~7,山西";
        //初始化字符串记录间的分隔符
        var recordSep = "~";
        //编号和名称间的分隔符
        var innerSep = ",";

        //源列表id
        var listBoxSouId = "listBoxSou";
        //目标列表id
        var listBoxDesId = "listBoxDes";

        var listBoxSou = null;
        var listBoxDes = null;

        //页面初始化
        function pageLoad() {debugger;
            //初始化变量
            listBoxSou = $("#" + listBoxSouId).get(0);
            listBoxDes = $("#" + listBoxDesId).get(0);

            var listDataSourceType = "string";
            var dataSource = getDataSource(listDataSourceType);
            bindData(listBoxSou,dataSource);
        }

        //可以有多种获取数据源的方式,也可以有多种承载数据源的介质
        function getDataSource(dataSourceType) {
            if (dataSourceType == "string") {
                return getStringDataSource();
            }

            return new Dictionary();
        }

        //获取字符串格式的列表数据源
        function getStringDataSource() {
            var dictionary = new Dictionary();

            var recordArray = initStr.split(recordSep);
            $.each(recordArray, function (index, record) {
                var idNameArray = record.split(innerSep);
                dictionary.add(idNameArray[0], idNameArray[1]);           
            });

            return dictionary;
        };

        //为列表绑定数据源
        function bindData(listBox, dataSource) {
            clearListBox(listBox);
            dataSource.each(function (index, item) {
                addOption(listBox, item.key, item.value);
            });
        };

        //向指定列表添加选项
        function addOption(listBox,text,value) {
            var option = document.createElement('option');
            option.value = value;
            option.text = text;
            listBox.add(option);
        };

        //清空列表的所有选项
        function clearListBox(listBox) {
            while (listBox.length > 0) {
                removeOption(listBox,0);
            }
        };

        //删除指定列表的指定项
        function removeOption(listBox, index) {
            listBox.remove(index);
        };

        $(document).ready(pageLoad);








        function KeyValuePair(key, value) {
            this.key = key;
            this.value = value;
        };

        KeyValuePair.prototype.key = null;
        KeyValuePair.prototype.value = null;

       


        

        function Dictionary() {
            this.clear();
        };
        

        Dictionary.prototype.keyValuePairs = null;

        Dictionary.prototype.length = 0;

        Dictionary.prototype.add = function (key, value) {
            this.keyValuePairs.push(new KeyValuePair(key, value));
            ++this.length;
        };

        Dictionary.prototype.remove = function (key) {
            for (var i = 0; i < this.length; i++) {
                if (this.keyValuePairs[i].key == key) {
                    this.keyValuePairs.splice(i, 0);
                    --this.length;
                    break;
                }
            }
        };

        Dictionary.prototype.get = function (key) {
            for (var i = 0; i < this.length; i++) {
                if (this.keyValuePairs[i].key == key) {
                    return this.keyValuePairs[i].value;
                    break;
                }
            }
        };

        Dictionary.prototype.getKey = function (value) {
            for (var i = 0; i < this.length; i++) {
                if (this.keyValuePairs[i].value == value) {
                    return this.keyValuePairs[i].key;
                    break;
                }
            }
        };

        Dictionary.prototype.clear = function () {
            this.keyValuePairs = new Array();
            this.length = 0;
        };

        Dictionary.prototype.contains = function (key) {
            if (this.get(key)) {
                return true;
            }
            return false;
        };

        Dictionary.prototype.each = function (callback) {
            if (callback != undefined && callback) {
                for (var i = 0; i < this.length; i++) {
                    callback.call(window, i, this.keyValuePairs[i]);
                }
            }
        };





        

  • 相关阅读:
    NGUI本地化
    Unity中的特殊文件夹
    NGUI3.7.4实现循环拖动
    一年
    倒计时 功能
    PV inverter启动 ----系列二
    关于几个其他的命令使用 【实时更新】
    QT学习系列-----5 --Qt 4.8.5的移植
    QT学习系列-----4 --Qt 版本及qwt
    经典数字信号处理图书的个人评述【转】
  • 原文地址:https://www.cnblogs.com/wufengtinghai/p/2322130.html
Copyright © 2011-2022 走看看