频道栏目
首页 > 资讯 > JavaScript > 正文

C#实现Javascript的Splice

18-06-26        来源:[db:作者]  
收藏   我要投稿
最近开始学习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语言写代码的感觉,要注意数组下标、数组边界和数组的大小。

相关TAG标签
上一篇:GVRP 的工作机制和工作模式
下一篇:你所不知道的JavaScript系列
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站