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 = { , , , , , }; 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方法的更多相关文章
- 详解JavaScript的splice()方法
from:http://www.jquerycn.cn/a_10447 在javascript中splice()方法,是一个很强的数组方法,它有多种用法.splice()主要用途是向数组的中部插入项. ...
- 详解 JavaScript 中 splice() 方法
splice() 方法是一个比较少用的方法,但是功能确实很好,并且在我们 coding 的时候,经常有需要 splice() 方法,先介绍一下该方法. 在 JavaScript 中 splice() ...
- javascript中的splice方法介绍&示例
javascript 中的 splice 方法很强大,它可以用于插入.删除或替换数组的元素. 下面来一一介绍! 删除:用于删除元素,两个参数,第一个参数(要删除第一项的位置),第二个参数(要删除的项数 ...
- JavaScript splice() 方法
定义和用法 splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目. 注释:该方法会改变原始数组. 例子 1 在本例中,我们将创建一个新数组,并向其添加一个元素: <script ...
- javascript数组Array强大的splice()方法
javascript的Array数组提供了强大的splice()方法, 用于对数组元素的增删改 1.删除-用于删除元素,两个参数,第一个参数(要删除第一项的位置),第二个参数(要删除的项数) 删除: ...
- JavaScript中的splice方法
splice方法根据传入的不同参数可分别实现删除和插入操作 使用splice(pra1,pra2,pra3)方法,需要为其提供如下参数: 1.pra1为其起始索引(即希望开始添加元素的地方) 2.pr ...
- 关于Javascript splice方法的一个坑。
w3c相关文档:http://www.w3school.com.cn/jsref/jsref_splice.asp bug:购物车计算价格的时候.加商品没问题,减商品的时候价格总是计算错误. 经排查发 ...
- Javascript:splice()方法实现对数组元素的插入、删除、替换及去重
定义和用法 splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目. 注释:该方法会改变原始数组. 语法: Array.prototype.splice(index,count[,el ...
- JavaScript引用类型之Array数组之强大的splice()方法
splice()方法可以说是Array数组最强大的方法,他的用法很多,主要用法是向数组的中部插入项! 下面是它的用法: arrayObject.splice(index,howmany,element ...
随机推荐
- python之爬虫--番外篇(一)进程,线程的初步了解
整理这番外篇的原因是希望能够让爬虫的朋友更加理解这块内容,因为爬虫爬取数据可能很简单,但是如何高效持久的爬,利用进程,线程,以及异步IO,其实很多人和我一样,故整理此系列番外篇 一.进程 程序并不能单 ...
- css3动画(animation)效果2-旋转的星球
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- bzoj2705Longge的问题
题目链接 题意很简单 $$ans=\sum_{i=1}^{n}gcd(i,n)$$ 然后推一下式子,求一下欧拉函数就好了 细节是由于$BZOJ$的评测计时策略, 不能线性筛啊$……$ 必须每个数单独筛 ...
- 修复已损坏的交换机IMG
1.找出与当前交换机匹配的升级镜像以及合适的BOOT启动程序(这要通过渠道获取) 2.搭建 TFTP 服务器. 3.启动交换机,链接console线缆 4.在 BOOT 模式,完成一下操作 1.配置I ...
- P4383 [八省联考2018]林克卡特树lct 树形DP+凸优化/带权二分
$ \color{#0066ff}{ 题目描述 }$ 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的 ...
- c语言-学生成绩信息系统
#include<stdio.h> #define N 100 int Count=0; struct stu { int num; char name[20]; int computer ...
- BZOJ - 3263 三维偏序
题意:定义元素为有序组(a,b,c),若存在x组(a_i,b_i,c_i)分别小于等于(a,b,c),则该元素的等级为x,求[0,n-1]等级的个数 cdq分治练手题,对a简单排序并去重,对b进行分治 ...
- C/C++入门易错点及常用小技巧
int型:绝对值在10^9范围内的整数都可以定义为int型 long long 型:如果long long型赋值大于2^23-1的初值,需要在初值后面加LL,否则会编译错误. float,double ...
- springMvc 中返回字符串 乱码解决
/** * produces=MediaType.APPLICATION_JSON_VALUE+";charset=utf-8" 乱码解决 * @param callback * ...
- [转] maven打包可运行的fat-jar的简单方法
[From] https://blog.csdn.net/tearsky253/article/details/75948721 问题 在使用“mvn package”命令编译application之 ...