C#实现Javascript的Splice方法

  最近开始学习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; }

  完成的代码及测试请查看https://github.com/axbxcxdx/ZxbLib

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

 

转载于:https://www.cnblogs.com/zhangxiaobin/p/9225019.html

你可能感兴趣的:(C#实现Javascript的Splice方法)