最近开始学习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 = { , , , , , }; int[] b = ArrayHelper.Splice(ref a, , ); Assert.Equal(new int[] { , , , }, a);
Assert.Equal(new int[] { , }, b);
}
        [Fact]
public void TrancateArrayAndInsertNewElements()
{
int[] a = { , , , , , }; int[] b = ArrayHelper.Splice(ref a, , , , , ); Assert.Equal(new int[] { , , , , , , }, a);
Assert.Equal(new int[] { , }, b);
}

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

        public static T[] Splice<T>(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, , 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, , 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语言写代码的感觉,要注意数组下标、数组边界和数组的大小。

C#实现Javascript的Splice方法的更多相关文章

  1. 详解JavaScript的splice()方法

    from:http://www.jquerycn.cn/a_10447 在javascript中splice()方法,是一个很强的数组方法,它有多种用法.splice()主要用途是向数组的中部插入项. ...

  2. 详解 JavaScript 中 splice() 方法

    splice() 方法是一个比较少用的方法,但是功能确实很好,并且在我们 coding 的时候,经常有需要 splice() 方法,先介绍一下该方法. 在 JavaScript 中 splice() ...

  3. javascript中的splice方法介绍&示例

    javascript 中的 splice 方法很强大,它可以用于插入.删除或替换数组的元素. 下面来一一介绍! 删除:用于删除元素,两个参数,第一个参数(要删除第一项的位置),第二个参数(要删除的项数 ...

  4. JavaScript splice() 方法

    定义和用法 splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目. 注释:该方法会改变原始数组. 例子 1 在本例中,我们将创建一个新数组,并向其添加一个元素: <script ...

  5. javascript数组Array强大的splice()方法

    javascript的Array数组提供了强大的splice()方法, 用于对数组元素的增删改 1.删除-用于删除元素,两个参数,第一个参数(要删除第一项的位置),第二个参数(要删除的项数) 删除: ...

  6. JavaScript中的splice方法

    splice方法根据传入的不同参数可分别实现删除和插入操作 使用splice(pra1,pra2,pra3)方法,需要为其提供如下参数: 1.pra1为其起始索引(即希望开始添加元素的地方) 2.pr ...

  7. 关于Javascript splice方法的一个坑。

    w3c相关文档:http://www.w3school.com.cn/jsref/jsref_splice.asp bug:购物车计算价格的时候.加商品没问题,减商品的时候价格总是计算错误. 经排查发 ...

  8. Javascript:splice()方法实现对数组元素的插入、删除、替换及去重

    定义和用法 splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目. 注释:该方法会改变原始数组. 语法: Array.prototype.splice(index,count[,el ...

  9. JavaScript引用类型之Array数组之强大的splice()方法

    splice()方法可以说是Array数组最强大的方法,他的用法很多,主要用法是向数组的中部插入项! 下面是它的用法: arrayObject.splice(index,howmany,element ...

随机推荐

  1. python-自定义异步非阻塞爬虫框架

    api import socket import select class MySock: def __init__(self, sock, data): self.sock = sock self. ...

  2. 24. 两两交换链表中的节点 leetcode

    题目: 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 示例: 给定 1->2->3->4, 你应该返回 ...

  3. selenium alert JS弹窗问题处理

    弹窗一般分为三种类型: 1.警告消息框(alert) 警告消息框提供了一个"确定"按钮让用户关闭该消息框,并且该消息框是模式对话框,也就是说用户必须先关闭该消息框然后才能继续进行操 ...

  4. HashMap源码解析 非原创

    Stack过时的类,使用Deque重新实现. HashCode和equals的关系 HashCode为hash码,用于散列数组中的存储时HashMap进行散列映射. equals方法适用于比较两个对象 ...

  5. 在红帽RHEL7.0里配置网卡的四种方法

    第一种方法 :采用vim编辑器来配置: 1.  如下图的步骤所示: 2.  输入这个命令后进行配置成下方图片里的内容: 3.  然后退出vim 编辑器,然后重新启动一下网络服务配置: 4.这些配置完后 ...

  6. 当页面滚动到距顶部一定高度时某DIV自动隐藏和显示

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. JVM_垃圾收集器

    最近刚好有时间,就简单的看了下JVM的几种垃圾回收器,它们都是计算机历史发展的产物,先简单的做一个整理,并没有哪一款垃圾收集器就一定是最优,还需要结合使用场景.参数配置等进行考量,根据系统情况搭配出尽 ...

  8. PHP网上支付

    1,网上支付方式两类:企业与银行对接和通过中间公司间接与银行对接. (1),企业与银行对接,优点:因为直接与银行进行财务结算,交易资金结算比较安全.适合资金流量比较大的企业,这种方案适合于,每月结算金 ...

  9. [Flex] 组件Tree系列 —— 阻止用户点击选中Tree中分支节点

    mxml: <?xml version="1.0" encoding="utf-8"?> <!--功能描述:阻止用户点击选中Tree中分支节点 ...

  10. pip安装本地文件

    I do a lot of development without an internet connection1, so being able to install packages into a ...