自己动手,实现一种类似ListT的数据结构(二)

前言:

首先,小匹夫要祝各位看官圣诞快乐,新年愉快~。上一篇文章《自己动手,实现一种类似List<T>的数据结构(一)》 介绍了一下不依靠List<T>实现的各种接口,仿造一个轻量级数据结构的过程。可能有的看官会有一些疑问,例如一些功能可以通过Linq提供的拓展来实现呀。此言不虚但也不全对,为了我们在工作中能方便的操作集合而提供的这些拓展方法(包括我们自己也可以构建的拓展方法),例如 Where,Any,Max,All...balalbala等等这些方法都是针对IEnumerable的对象进行扩展的,也就是说需要实现 IEnumerable接口。但是前面已经说了,小匹夫的用意是不实现各种List<T>继承的接口。另外小匹夫的初衷是仿造和拓展 List<T>,将工作中需要使用到的各种功能集成到一个类中,所以有些现成的拓展方法不需要,有一些没有的方法小匹夫也会自己实现一下(当然不是通过给现成的类添加拓展方法这种方式)。当然这篇文章介绍的东西还不成熟,需要慢慢完善,小匹夫也是把这个当做一个学习和实践的机会。好啦,解释完毕,那就介绍下今天的内容吧:

  1. 实现的方法的名称和说明列表
  2. 增加了3个委托来抽象3种情况。
  3. Map:通过委托把EggArray<T>中的每个值映射到一个新的EggArray<T>中
  4. Difference:返回的值来自EggArray<T>中,但同时不是传入的Other里面的值
  5. Invoke:在EggArray<T>的每个元素上执行methodName方法。
  6. Pluck:萃取EggArray<T>中某字段值,返回一个数组,由于字段类型不确定,所以需要装箱。
  7. Shuffle:返回一个随机乱序的T[]副本。

那么下面我们就书接上文,继续我们仿照和拓展List<T>的步伐。

Underscore.js的前缘

咦,这不是一篇关于Csharp的文章吗?怎么把JS给干出来?哈哈,当然技术上并没有什么必然的关系,只不过是小匹夫之前使用过cocos2d这套游戏引擎开发过游戏,有一段时间也很痴迷于cocos2d-js这种使用JS就能开发原生游戏的能力。所以也接触了一些js库,对Underscore.js更是情有独钟。所以一提到要模仿List<T>这种内部其实是Array的数据结构,一个灵感就是为何不尝试实现一些Underscore.js数组部分的若干功能呢?所以下表EggArray<T>的新增方法中有部分借鉴于Underscore.js。

新增方法表

新增方法说明
First 返回EggArray<T> 的第一个元素。传递 n参数将返回数组中从第一个元素开始的n个元素
Last 返回EggArray<T> 的最后一个元素。传递 n参数将返回数组中从最后一个元素开始的n个元素
Slice 切割
Get 预留
Set 预留
AddFirst 将对象添加到 EggArray<T> 的起始处。
RemoveLast EggArray<T> 中移除特定对象的最后一个匹配项。
ContainsStrict 确定某元素是否在 EggArray<T> 中。(严格判断是否是同一个对象)
IndexOfStrict 搜索指定的对象,并返回整个 EggArray<T> 中第一个匹配项的从零开始的索引。(同上)
TryGet 获取指定类型对象
LastIndexOf 搜索指定的对象,并返回整个 EggArray<T> 中第一个匹配项的从结尾开始的索引。
Map 通过委托把EggArray<T>中的每个值映射到一个新的EggArray<T>
Filter 遍历EggArray<T>中的每个值,返回包含所有通过predicate真值检测的元素值。
Without 返回一个删除所有values值后的 EggArray<T>副本。
FindEggArray<T>中逐项查找,返回第一个通过predicate迭代函数真值检测的元素值
Every如果EggArray<T>中的所有元素都通过predicate的真值检测就返回true
Some如果EggArray<T>中有任何一个元素通过 predicate 的真值检测就返回true
Partition拆分一个EggArray<T>为两个数组:  第一个数组其元素都满足predicate迭代函数, 而第二个的所有元素均不能满足predicate迭代函数
Difference返回的值来自EggArray<T>中,但同时不是传入的Other里面的值
Uniq返回 EggArray<T>去重后的副本
InvokeEggArray<T>的每个元素上执行methodName方法。
Pluck萃取EggArray<T>中元素某属性值,返回一个数组。
Shuffle返回一个随机乱序的T[]副本
SampleEggArray<T>中产生一个随机样本。传递一个数字表示从EggArray<T>中返回n个随机元素。否则将返回一个单一的随机项。

 

各位看官可以看到,增加了许多挺有趣的功能。为了能将表中的功能名字变成真正的功能,我们还需要对上一篇文章中的变量&属性部分做一些增改,如下我们增加了3个委托来抽象3种情况。

//定义三个委托来处理具体逻辑
public delegate void IterationHandler(T item);
public delegate bool IterationBoolHandler(T item);
public delegate T IterationVauleHandler(T item);

同时为了能测试我们的功能,我们还要定义一个用来被当做元素测试的类。

//被测试类
public class TargetClass
{public int id;public string name;public TargetClass(int id){this.id = id;this.name = "NO. " + id;}public void Hi(){Debug.Log ("say hi");}
}

同时还要有一个测试的环境,因为小匹夫是用mac做unity3d的开发,所以就直接使用unity3d的环境了。

/// <summary>
/// Egg array test.Based on Unity3D,各个元素的id为0-9
/// </summary>
using UnityEngine;
using System.Collections;
using EggToolkit;
public class EggArrayTest : MonoBehaviour {EggArray<TargetClass> testArray = new EggArray<TargetClass>();// Use this for initializationvoid Start () {for(int i = 0; i < 10; i++){TargetClass test = new TargetClass(i);testArray.Add(test);}
//        Test_Difference();
//        Test_Invoke();
//        Test_Pluck();
//        Test_Shuffle();
//        Test_Map();
    }void Update () {}
}

 

下面就让小匹夫带领大家分析几个具体的函数,并进行下测试吧。

Map:

使用了IterationVauleHandler这个委托,即需要返回一个T类型的值。

//通过委托把EggArray<T>中的每个值映射到一个新的EggArray<T>中
public EggArray<T> Map(EggArray<T>.IterationVauleHandler handler)
{EggArray<T> targetArray = new EggArray<T>(this.capacity);for(int i = 0; i < this.count; i++){T t = handler(this.items[i]);targetArray.Add(t);}return targetArray;
}

EggArrayTest中实现Test_Map这个方法:

void Test_Map()
{EggArray<TargetClass> newArray = testArray.Map(delegate(TargetClass item) {TargetClass newItem = new TargetClass(1);newItem.id = item.id * 10;return newItem;});newArray.Foreach(delegate(TargetClass item) {Debug.Log (item.id);});
}

//原元素的id为0-9,输出为0,10,20...90

 

Difference:

调用了Filter方法,其中Filter方法的参数是一个IterationBoolHandler委托,即一个返回bool值的委托。具体可以看Filter的实现。

/// <summary>
/// Difference the specified others.
///输出不包含others中元素的EggArray<T>
/// </summary>
/// <param name="others">Others.</param>
public EggArray<T> Difference(EggArray<T> others)
{EggArray<T> targetArray = new EggArray<T>();targetArray = this.Filter(delegate(T item) {bool b = !others.Contains(item);return b;});return targetArray;
}

EggArrayTest中实现Test_Difference这个方法:

 

//作为参数传入的EggArray<T>由testArray的第5,第9这2个元素组成
void Test_Difference()
{EggArray<TargetClass> differentArray = new EggArray<TargetClass>();differentArray.Add(testArray.Get(5));differentArray.Add(testArray.Get(9));testArray.Difference(differentArray).Foreach(delegate(TargetClass item) {Debug.Log(item.name);});
}
//输出缺少no. 5,no. 9这两个name

 

Invoke:

EggArray<T>的每个元素上执行methodName方法。

/// <summary>
/// Invoke the specified methodName.
/// 每个元素上执行methodName方法,若方法不存在则抛出exception
/// </summary>
/// <param name="methodName">Method name.</param>
public void Invoke(string methodName)
{Type t = typeof(T);var method = t.GetMethod(methodName);if(method == null)throw new Exception("没有找到指定的方法哦~,可能不叫" + methodName);for(int i = 0; i < this.count; i++){method.Invoke(this.items[i], null);}
}

EggArrayTest中实现Test_Invoke这个方法:

//调用TargetClass的HI()方法
void Test_Invoke()
{testArray.Invoke("Hi");
}//输出:say hi

 

Pluck:

萃取EggArray<T>中某字段值,返回一个数组,由于字段类型不确定,所以需要装箱。当传入的名称无法查找到该字段时,抛出exception。

/// <summary>
/// Pluck the specified fieldName.
/// 萃取某字段值,返回一个数组
/// 由于字段类型不确定,所以需要装箱
/// </summary>
/// <param name="fieldName">Field name.</param>
public object[] Pluck(string fieldName)
{Type t = typeof(T);object[] targetArray = new object[this.count];var field = t.GetField(fieldName);if(field == null)throw new Exception("没有找到指定的field哦~,可能不叫" + fieldName);for(int i = 0; i < this.count; i++){object value = field.GetValue(this.items[i]);targetArray[i] = value;}return targetArray;
}

EggArrayTest中实现Test_Pluck这个方法:

 

//获取各个元素 字段id的值
void Test_Pluck()
{object[] testObj = testArray.Pluck("id");string testString = string.Empty;for(int i = 0; i < testObj.Length; i++){testString = testObj[i].ToString();Debug.Log ("field value is " + testString);}
}//输出为0-9

 

 

Shuffle:

返回一个随机乱序的T[],下面看代码

/// <summary>
/// Shuffle this instance.
/// 返回一个随机乱序的副本
/// </summary>
public T[] Shuffle()
{T[] shuffled = new T[this.count];Random random = new Random();for (int index = 0, rand; index < this.count; index++) {rand = random.Next(index);if (rand != index) shuffled[index] = shuffled[rand];shuffled[rand] = this.items[index];}return shuffled;
}

EggArrayTest中实现Test_Shuffle这个方法:

 

//
void Test_Shuffle()
{TargetClass[] test = testArray.Shuffle();for(int i = 0; i < test.Length; i++){Debug.Log (test[i].name);}
}//默认顺序为NO. 0 ~ NO. 9
//乱序后,见图

 

好了,这周就到这里~小匹夫最近也在赶项目的途中,所以测试和修改的精力也被消耗了很多。过完元旦之后,再继续~

末了还是要说一声:各位元旦快乐~

完整的代码和测试可以在这里获取:https://github.com/chenjd/Unity3D_EggArray

装模作样的声明一下:本博文章若非特殊注明皆为原创,若需转载请保留原文链接及作者信息慕容小匹夫

转载于:https://www.cnblogs.com/murongxiaopifu/p/4176620.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459774.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

局域网内连接MySQL

2019独角兽企业重金招聘Python工程师标准>>> 局域网内连接MySQL 博客分类&#xff1a; MySQL MySQL局域网连接grant 我们都知道连接MySQL一般用的语句就是 jdbc:mysql://localhost:3306/database&#xff0c; 但是当你要连接到其他机器上的mysql的时候&#xff0c;…

[leetcod] Clone Graph

题目&#xff1a; Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. OJs undirected graph serialization: Nodes are labeled uniquely. We use # as a separator for each node, and , as a separator for node label and …

【iOS7一些总结】9、与列表显示(在):列表显示UITableView

列表显示&#xff0c;顾名思义它是在一个列表视图的形式显示在屏幕上的数据的内容。于ios在列表视图UITableView达到。这个类在实际应用中频繁&#xff0c;是很easy理解。这里将UITableView的主要使用方法总结一下以备查。UITableView定义在头文件UITableView.h中&#xff0c;详…

SpringMVC(一):环境搭建

2019独角兽企业重金招聘Python工程师标准>>> //TODO 转载于:https://my.oschina.net/u/1020238/blog/505272

DockPanel 类

DockPanel 类 .NET Framework 4.5其他版本此主题尚未评级 - 评价此主题定义您可水平或垂直排列子元素的区域&#xff0c;互相。 继承层次结构 System.Object System.Windows.Threading.DispatcherObjectSystem.Windows.DependencyObjectSystem.Windows.Media.VisualSystem.Wind…

【分布式计算】MapReduce的替代者-Parameter Server

原文&#xff1a;http://blog.csdn.net/buptgshengod/article/details/46819051 首先还是要声明一下&#xff0c;这个文章是我在入职阿里云1个月以来&#xff0c;对于分布式计算的一点肤浅的认识&#xff0c;可能有些地方不够妥善&#xff0c;还请看官可以指出不足的地方&#…

iOS开发多线程篇—线程安全

iOS开发多线程篇—线程安全 一、多线程的安全隐患 资源共享 1块资源可能会被多个线程共享&#xff0c;也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象、同一个变量、同一个文件 当多个线程访问同一块资源时&#xff0c;很容易引发数据错乱和数据安全问题 示例…

Android Ion 框架 文件下载

为什么80%的码农都做不了架构师&#xff1f;>>> ion是的一个安卓异步网络和图片加载库。 特性 异步下载&#xff1a;下载图片 (用ImageViews 或者 Bitmaps显示)&#xff1b;下载JSON文件 (通过Gson解析)&#xff1b;下载字符串&#xff1b;下载文件&#xff1b;Flu…

CSS基础----元素分类

2019独角兽企业重金招聘Python工程师标准>>> 块级元素特点&#xff1a; 1、每个块级元素都从新的一行开始&#xff0c;并且其后的元素也另起一行。 2、元素的高度、宽度、行高以及顶和底边距都可设置。 3、元素宽度在不设置的情况下&#xff0c;是它本身父容器的100…

Linux 高可用(HA)集群之keepalived

一、keepalived介绍1、Keepalived 定义Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案&#xff0c;可以利用其来避免单点故障。一个LVS服务会有2台服务器运行Keepalived&#xff0c;一台为主服务器&#xff08;MASTER&#xff09;&#xff0c;一台为备份服务器&#…

java 将要死亡_人在即将死亡的时候,能意识到自己将要死亡了吗?科学家给出答案...

引言&#xff1a;自然界内大多数生物都敬畏生命&#xff0c;也害怕死亡。毕竟&#xff0c;死亡意味着结束与告别&#xff0c;将死之人多会留恋世间的人或事。那么&#xff0c;在临死之前&#xff0c;人会意识到自己将走向死亡吗&#xff1f;人类对长生不老的追求古已有之&#…

C#开发微信门户及应用(24)-微信小店货架信息管理

C#开发微信门户及应用(24)-微信小店货架信息管理 原文:C#开发微信门户及应用(24)-微信小店货架信息管理在前面微信小店系列篇《C#开发微信门户及应用(22)-微信小店的开发和使用》里面介绍了一些微信小店的基础知识&#xff0c;以及《C#开发微信门户及应用(23)-微信小店商品管理…

【百度地图API】——如何用label制作简易的房产标签

【百度地图API】——如何用label制作简易的房产标签 原文:【百度地图API】——如何用label制作简易的房产标签摘要&#xff1a; 最近&#xff0c;API爱好者们纷纷说&#xff0c;自定义marker太复杂了&#xff01;不仅定义复杂&#xff0c;连所有的dom事件都要自己重新定义。有没…

【svn】设置过滤文件

2019独角兽企业重金招聘Python工程师标准>>> .classpath target .project .settings *.o *.lo *.la *.al .libs *.so *.so.[0-9]* *.a *.pyc *.pyo *.rej *~ #*# .#* .*.swp .DS_Store 转载于:https://my.oschina.net/sourcecoding/blog/509169

php开启错误日志,PHP开启error_log 错误日志

对于一些访问没有明显错误提示的PHP页面&#xff0c;我们可以通过error_log来做进一步的判定。但出于种种原因&#xff0c;有些服务器并没有开启PHP的error_log功能。可以暂时开启一下错误日志&#xff1a;编辑php.ini&#xff0c;将log_errors设置为on&#xff1a;log_errors …

unity3d-小案例之角色简单漫游

准备资源 我这里从网上下载一个角色模型&#xff0c;里面有一组动画。有站立、奔跑、杀怪等 我们来实现角色的前后左后移动&#xff0c;即键盘上的WSDA键&#xff0c;这里因为没有行走的动画。索性就用奔跑代替了&#xff01;&#xff01; 暂时先不计较代码冗余的情况。因为我也…

PopupWindow在项目中的使用 并指定位置及加入动画效果

2019独角兽企业重金招聘Python工程师标准>>> 项目做到一期收尾阶段&#xff0c;突然要用到弹出窗口&#xff0c;于是自然而然的就想起了PopupWindow这个组件了&#xff0c;才发现平时用的少&#xff0c;对这个组件几乎是完全无知的状态啊。 于是恶补一番 现在放出学…

php 图片无法删除,php如何删除上传的图片

php删除上传的图片的方法&#xff1a;首先检查上传文件是否在允许上传的类型&#xff1b;然后获取图片的完整路径&#xff1b;最后通过“unlink(“uppic/”.$img);”方法删除图片即可。简单的PHP上传图片和删除图片示例代码分享一例简单的PHP上传图片和删除图片示例代码&#x…

贝克汉姆-囚

转载于:https://www.cnblogs.com/andyxl/p/4215954.html

Androida规划nt打包

1.准备工作 &#xff08;1&#xff09;首先安装好ant工具 &#xff08;2&#xff09;生成keystore 在jdk的bin文件夹下 输入keytool -genkey -alias android.keystore -keyalg RSA -validity 20000 -keystore android.keystore 按操作输入就可以&#xff0c;记住password。 &am…