欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#实现Javascript的Splice

程序员文章站 2022-10-11 09:10:02
最近开始学习javascript语言,看到splice方法,以下引用其说明:该方法是一个通用删除和插入元素的方法,它可以在数组指定的位置开始删除或插入元素。其包括3个参数:第一个参数指定插入的起始位...
最近开始学习javascript语言,看到splice方法,以下引用其说明:该方法是一个通用删除和插入元素的方法,它可以在数组指定的位置开始删除或插入元素。其包括3个参数:第一个参数指定插入的起始位置,第二个参数指定要删除元素的个数,第三个参数开始表示插入的具体元素,方法返回被删除的元素数组。觉得此方法很不错,所以也想尝试用c#实现一个。

刚开始马上想到用扩展方法实现,如此才会跟javascript里的用法一样。很快发现c#里的数组大小是固定的,不能修改,而javascript里的splice方法需要动态的改变数组的大小。c#的system.array类没有提供修改数组的方法,包括clear()方法也仅仅是将数组中的每个元素都设置为其默认值(false,0或null);resize()方法则是创建新数组,并将所有元素复制到新数组。最终只能以比较丑陋的helper类的方式实现,如有高人知道更好的方式,请不吝赐教。

由于需求比较明确,所以直接写了第一个测试,即删除数组第3、第4个元素并返回被删除的元素。tdd是很好的开发方法,让你目标明确,明白自己下一步要做什么,以及知道自己是否已经达成了目标,也让你放心的去重构代码。这里不再一步步说明怎么按照tdd的要求,用最少的代码达成测试的要求,直接贴出两段测试,以说明splice方法是怎么工作的。这也是tdd的好处之一,测试就是示例代码。

[fact]
        public void trancatetwoelements()
        {
            int[] a = { 1, 2, 3, 4, 5, 6 };

            int[] b = arrayhelper.splice(ref a, 2, 2);

            assert.equal(new int[] { 1, 2, 5, 6 }, a);
            assert.equal(new int[] { 3, 4 }, b);
        }
 [fact]
        public void trancatearrayandinsertnewelements()
        {
            int[] a = { 1, 2, 3, 4, 5, 6 };

            int[] b = arrayhelper.splice(ref a, 2, 2, 7, 8, 9);

            assert.equal(new int[] { 1, 2, 7, 8, 9, 5, 6 }, a);
            assert.equal(new int[] { 3, 4 }, b);
        }

代码的整体思路是,先新建两个数组,分别用于存放被删除元素和剩余的元素加上插入的新元素(如果有的话),然后把要删除的元素拷贝到用于保存被删除元素的数组,接着拷贝源数组删除位置前的需要保留的元素到新数组,然后把要插入的元素拷贝到新数组,最后把源数组末尾的元素拷贝到新数组。还是用代码说话会计较清楚:

 public static t[] splice(ref t[] sourcearray, int sourceindex, int length, params t[] insertedelements)
        {
        // 此处省略防卫语句

            // 如果要截取的元素个数大于从sourceindex开始到数组结束的元素个数
            int acturallength = (sourceindex + length) > sourcearray.length ? (sourcearray.length - sourceindex) : length;

            var deleteditems = new t[acturallength];
            array.constrainedcopy(sourcearray, sourceindex, deleteditems, 0, acturallength);

            int arraylengthdifference = insertedelements.length - acturallength;
            int newarraylength = sourcearray.length + arraylengthdifference;
            var newarray = new t[newarraylength];

            int newarraycopyedelementsindex = sourceindex;
            array.copy(sourcearray, newarray, newarraycopyedelementsindex);

            array.constrainedcopy(insertedelements, 0, newarray, newarraycopyedelementsindex, insertedelements.length);
            newarraycopyedelementsindex += insertedelements.length;

            int remainedelementsindex = sourceindex + acturallength;
            // 源数组末尾还有元素才进行拷贝
            if (remainedelementsindex < sourcearray.length)
            {
                array.constrainedcopy(sourcearray, remainedelementsindex, newarray, newarraycopyedelementsindex, sourcearray.length - remainedelementsindex);
            }

            sourcearray = newarray;

            return deleteditems;
        }  

通过写这段代码体会到了日常用惯了list等集合类,现在用数组去存放操作元素好像又回到c语言写代码的感觉,要注意数组下标、数组边界和数组的大小。