最新Classworking工具箱分析泛型数据结构汇总

C l a s s w o r k i n g工具箱分析泛型数据结构Java™ 5 泛型把详细的类型信息编码到类文件中。

许多类型的工具都可以从全面的类型信息提供的改进的数据结构中受益,但是要把这个信息变成有用的形式可能有些困难。

为了让这个工作更容易些,系列作者 Dennis Sosnoski 围绕ASM Java 字节码操纵框架构建了一个数据结构分析程序,可以解释泛型信息,为应用程序使用的数据的实际数据类型创建深度的视图。

类处理工具实际上就是一个把其他程序当成数据的程序,通常会修改或重新塑造目标程序,以满足某些目的。

在把程序当成数据的时候,如果构建一个关于程序自身内部数据结构的模型,协助对修改进行指导,那么通常是有用的。

可以利用反射,在第一次把目标程序的类文件装入 JVM 之后,创建这种类型的模型。

也可以用框架直接从类文件解码出数据结构信息,甚至从源代码进行解码。

不论采用何种技术,目的都是得到应用程序使用的对象之间关系的尽可能全面的视图。

Java 5 程序中的泛型信息,提供了应用程序数据结构的详细地图。

泛型之前的程序,只要运行到 Java 集合类或使用无类型引用的应用程序类时,数据结构的分析就走进了死胡同。

如果没有某种形式的外部信息,就没有办法知道无类型引用链接到什么类型的对象。

在使用泛型时,可以提供附加信息作为源代码的一部分,然后编译器会把附加的引用类型信息直接整合到二进制的类文件中。

利用这种内嵌的泛型信息是建立对象之间关系的更丰富视图的关键所在。

向专家 Dennis Sosnoski 请教关于 JVM 和字节码的问题如果对于这个文章系列中涉及的材料有意见和问题,以及有其他任何关于 Java 字节码、Java 二进制类格式或一型与ASM”)中,我首先介绍了使用反射得到泛型信息的基础知识,然后对于使用 ASM 字节码框架处理类文件的原始泛型信息作了详细介绍。

在这篇文章中,我把 ASM 技术用得更深入一点儿,在泛型类定义中使用类型替换来构建目标应用程序数据结构的增强视图。

在进入分析类所使用的实际 ASM 代码之前,我先介绍表示和组织数据结构信息时一些比较简单的问题。

表示数据结构在构建分析程序时的第一个问题是,定义目标程序使用的数据结构的表示形式。

这必须不仅包含每个字段值的表示,还要包含每个值的类型信息的表示。

因为我想在这一期中演示泛型的解码,所以类型信息需要包含泛型引用所使用的具体的参数类型。

清单 1 显示了我用作基本数据结构表示的类。

FieldDescription 类只是个简单的数据类,容纳字段名称、签名和字段类型的引用。

正如我在前一期中介绍的,签名是泛型添加到类文件格式中的项目;只有对泛型的引用才有签名。

签名定义了泛型实际使用的参数类型,所以它提供了处理类型替换时需要的信息。

对于没有签名的字段,将只使用 null 值。

最后,字段类型都是 TypeDescription 类的实例,如清单 1 所示:清单 1. 基本数据结构类private final String m_name;// only fields that are of generic types have signaturesprivate final String m_signature;// type only defined when parameter types are definedprivate final TypeDescription m_type;public FieldDescription(String name, String sig, TypeDescription type) { m_name = name;m_signature = sig;m_type = type;}public String getName() {return m_name;}public String getSignature() {return m_signature;}public TypeDescription getType() {return m_type;}}public abstract class TypeDescription{public static final FieldDescription[] EMPTY_FIELD_ARRAY = {};private final String m_descriptor;protected TypeDescription(String dtor) {m_descriptor = dtor;}public boolean isArray() {return false;}public TypeDescription getArrayItemType() {throw new IllegalStateException("Not an array");}public boolean isPrimitive() {return false;}public FieldDescription[] getFields() {return EMPTY_FIELD_ARRAY;}public String getDescriptor() {return m_descriptor;}public boolean equals(Object obj) {if (obj == this) {return true;} else if (obj instanceof TypeDescription) {return m_descriptor.equals(((TypeDescription)obj).m_descriptor);} else {return false;}}public int hashCode() {return m_descriptor.hashCode();}public abstract String toString();}TypeDescription 类只是个抽象基类,其中定义了处理三种类型的方法:原生类型、数组和类实例。

这个基类以类型描述符的形式包含了一个值。

我用于这个类的类型描述符大致符合 JVM 规范定义的类型描述符的形式,但是有些扩展,添加了泛型具体“版本” 的实际参数类型列表。

这个扩展允许把Ljava/util/Map<Ljava/lang/String;Ljava/lang/String;>; 这种形式的描述符作为类型系统的一部分。

回页首组织数据结构组织数据结构信息的问题比表示信息的问题略微复杂一些。

组织信息的基本问题在于数据结构经常是递归的:一个类中可能有一个字段,这个字段引用这个类的一个实例,或者它引用的一个类可能直接或间接地引用回到原来的类。

所以,只想直接展开结构,可能会形成无限的递归循环。

我使用目录技术来处理这种递归引用。

在找到类引用时,检查目标,查看这个类以前是否已经看到过。

如果是,那么目录就返回现有的描述。

如果没有,则目录创建新的描述实例,并立即把描述添加到目录(甚至在描述的完整细节可用之前就添加)。

清单 2 显示了这个 TypeDirectory 类的基本代码,现在暂时不管它,以后会添加处理泛型的一些细节:清单 2. TypeDirectory 类public class TypeDirectory{/** Source for binary class representations. */private final BinaryClassLoader m_loader;/** Field list for all arrays. */private final FieldDescription[] m_arrayFields;/** Map from descriptor or signature to type for all non-generic types,* including generics with substitutions. */private HashMap<String,TypeDescription> m_typeMap =new HashMap<String,TypeDescription>();.../*** Constructor. Initializes the type directory with descriptions of* primitive types.** @param loader binary class loader*/public TypeDirectory(BinaryClassLoader loader) {m_loader = loader;addType(new PrimitiveTypeDescription("B", "byte"));addType(new PrimitiveTypeDescription("C", "char"));addType(new PrimitiveTypeDescription("D", "double"));addType(new PrimitiveTypeDescription("F", "float"));TypeDescription inttype = new PrimitiveTypeDescription("I", "int");addType(inttype);addType(new PrimitiveTypeDescription("J", "long"));addType(new PrimitiveTypeDescription("S", "short"));addType(new PrimitiveTypeDescription("V", "void"));addType(new PrimitiveTypeDescription("Z", "boolean"));m_arrayFields = new FieldDescription[] {new FieldDescription("int", null, inttype)};}/*** Add type description to type directory.** @param desc type description to add*/public void addType(TypeDescription desc) {m_typeMap.put(desc.getDescriptor(), desc);}/*** Add generic class to template directory.** @param tmpl generic template to add*/public void addTemplate(GenericTemplate tmpl) {m_templateMap.put(tmpl.getDescriptor(), tmpl);}/*** Get description for the type. The type may be a primitive, an array, or a * class. If the type is a generic class, it will be treated as though all* type variables used their lower bounds.** @param dtor type descriptor* @return type description*/public TypeDescription getTypeInstance(String dtor) {// check for an existing descriptionTypeDescription desc = m_typeMap.get(dtor);if (desc == null) {// new description needed - must be array or classif (dtor.charAt(0) == '[') {desc = new ArrayClassDescriptor(dtor,getTypeInstance(dtor.substring(1)));} else {// parse binary class to build descriptionbyte[] byts = m_loader.getBytes(dtor);desc = new SimpleClassDescription(dtor, byts, this);}}return desc;}/*** Get description for generic class with specific type substitutions.** @param sig field signature with type substitutions* @param types actual types used for instance (values may be* <code>null</code> if no substitution defined)* @return type description*/public TypeDescription getSignatureInstance(String sig,TypeDescription[] types) {// first check for direct match on substituted signatureTypeDescription desc = (TypeDescription)m_typeMap.get(sig);if (desc == null) {// no direct match, first handle arrayif (sig.charAt(0) == '[') {desc = new ArrayClassDescriptor(sig,getSignatureInstance(sig.substring(1), types));} else {...}}return desc;}/*** Get description for signature with type mapping.** @param sig field signature for type variables* @param tmap type mapping for variables* @return type description*/public TypeDescription getMappedSignatureInstance(String sig,HashMap<String,TypeDescription> tmap) {...}.../*** Descriptor for primitive "class." There's really nothing to record for a * primitive type except the name, so that's all this does. Because instances * only need to be created and added to the directory at initialization, this * is an inner class.*/private static class PrimitiveTypeDescription extends TypeDescription{private final String m_externalName;private PrimitiveTypeDescription(String iname, String xname) {super(iname);m_externalName = xname;}public boolean isPrimitive() {return true;}public String toString() {return m_externalName;}}/*** Descriptor for array class. This is just a wrapper around the descriptor* for the item type, with the same field list used for all arrays.*/private class ArrayClassDescriptor extends TypeDescription{private final TypeDescription m_itemType;protected ArrayClassDescriptor(String name, TypeDescription item) {super(name);m_itemType = item;}public boolean isArray() {return true;}public TypeDescription getArrayItemType() {return m_itemType;}public FieldDescription[] getFields() {return m_arrayFields;}public String toString() {return m_itemType + "[]";}}}清单 2 的代码使用内部的 PrimitiveTypeDescription 和 ArrayTypeDescription 类直接处理原生类型和数组类型。

合集下载

J2EE课程设计《技术应用指导》——第1章 Java集合和泛型技术及应用(第4部分)

J2EE课程设计《技术应用指导》——第1章 Java集合和泛型技术及应用(第4部分)

第1章Java集合和泛型技术及应用(第4/4部分)1.1深入理解和应用Java泛型技术1.1.1有届泛型类型及在项目中的应用1、对泛型的“类型通用性”加以一定的限制(1)泛型的“类型通用性”会为应用系统在运行过程中带来一定的性能开销泛型的“类型通用性”能够为读者带来代码的灵活性和功能实现的通用性,但这样的“灵活性”和“通用性”也为应用系统在运行过程中带来一定的系统性能开销。

因此,如果在具体应用中并不需要程序代码具有非常高的“灵活性”和“通用性”的要求,如果读者能够预知或者能够确定数据的可能类型的编程应用场合下,可以对泛型的“类型通用性”加以一定的限制。

这样的限制能够减少参数的数据类型在转换过程中所可能带来的系统性能开销,而且也能够在一定的程度上避免类型转换过程中有可能会出现的各种可能的错误。

(2)对泛型的“类型通用性”加以一定的限制在许多应用环境下,方法的功能实现代码中的各种参数的数据类型是已知的数据类型或者是有类型范围的,比如下面的泛型类代码示例中的泛型类型GenericType在具体应用时实际只能为UserInfoBase类及其子类的类型范围。

public class GenericTypeDemo<GenericType> {}由于在上面的代码示例中的泛型类型GenericType定义符是没有任何的类型限制的,实际上也就相当于该类为ng.Object类型——也就是相当于下面的有届泛型类定义:public class GenericTypeDemo<GenericType extends Object> {}这样的泛型类定义有点“太泛”了,因为系统中的数据类型实际只能是UserInfoBase 类及其子类的类型范围,不可能为其他的数据类型。

因此,读者可以对上面的有届泛型类型定义进一步类型具体化以缩小数据类型的范围。

2、有届泛型类型定义的语法在Java中的有届泛型类型定义是利用extends关键字来限定类型参数只能是某个类或它的子类的数据类型,如果存在有多个不同的限定时,则要采用“&”符号分开不同的类型名称。

泛型的使用方法

泛型的使用方法

泛型的使用方法
泛型的使用方法主要有三种:泛型类、泛型接口和泛型方法。

1. 泛型类:在类名的后面用尖括号括起一个(或多个)类型参数。

类型参数的作用域是定义这个类型参数的整个类,但不包括静态成员方法。

因为其类型参数不定,无法直接分配储存空间。

2. 泛型方法:在方法的返回类型前面加上一个类型参数T,并有<>括起来。

3. 泛型接口:在接口名之后加上类型参数。

通过使用泛型,可以更灵活地处理数据,避免代码的重复,提高代码的复用性。

Java中泛型T和ClassT以及Class?的理解(转)

Java中泛型T和ClassT以及Class?的理解(转)

Java中泛型T和ClassT以及Class?的理解(转)注意:class是java的关键字, 在声明Java类时使⽤;Class类的实例表⽰Java应⽤运⾏时的类(class ans enum)或接⼝(interface and annotation)(每个Java类运⾏时都在JVM ⾥表现为⼀个Class对象,可通过类名.class,类型.getClass(),Class.forName("类名")等⽅法获取Class对象)。

数组同样也被映射为为Class对象的⼀个类,所有具有相同元素类型和维数的数组都共享该Class对象。

基本类型boolean,byte,char,short,int,long,float,double和关键字void同样表现为Class对象。

T bean ;Class<T> bean;Class<?> bean;单独的T代表⼀个类型,⽽Class<T>和Class<?>代表这个类型所对应的类Class<T>在实例化的时候,T要替换成具体类Class<?>它是个通配泛型,?可以代表任何类型<? extends T>受限统配,表⽰T的⼀个未知⼦类。

<? super T>下限统配,表⽰T的⼀个未知⽗类。

public T find(Class<T> clazz, int id);根据类来反射⽣成⼀个实例,⽽单独⽤T没法做到。

Object类中包含⼀个⽅法名叫getClass,利⽤这个⽅法就可以获得⼀个实例的类型类。

类型类指的是代表⼀个类型的类,因为⼀切皆是对象,类型也不例外,在Java使⽤类型类来表⽰⼀个类型。

所有的类型类都是Class类的实例。

getClass()会看到返回Class<?>。

JDK中,普通的Class.newInstance()⽅法的定义返回Object,要将该返回类型强制转换为另⼀种类型;但是使⽤泛型的Class<T>,Class.newInstance()⽅法具有⼀个特定的返回类型;参考:。

[整理]Classworking工具箱泛型与ASM.

[整理]Classworking工具箱泛型与ASM.

Java™ 5 泛型提供了对于许多classworking 都非常有用的信息。

尽管Java 反射可用于为载入的类获取泛型信息,但要求类必须载入到JVM 中,这是一个很大的缺点。

在本文中,classworking 精神领袖Dennis Sosnoski 展示了ASM Java 字节码操纵框架怎样在无需经过Java classloading 处理的情况下提供对泛型信息的灵活访问。

在文中,他还深入探讨了泛型的二进制类表示。

Java 5 程序中的泛型信息对于理解程序的数据结构非常有帮助。

在上一期中,我为您介绍了如何使用运行时反射来访问泛型信息。

如果您仅对获得载入JVM 中的类的信息感兴趣,那么这种反射方法非常有效。

但有时您可能希望在载入类之前对其加以修改,或者希望在不载入类的情况下研究数据结构。

在这样的时候,反射对您来说就不再是一种行之有效的办法——反射将JVM 类结构作为信息源使用,因此它仅对已由JVM 装载的类起作用。

要想在不将类载入JVM 的情况下访问泛型信息,您需要一种读取存储在二进制类表示内的泛型信息的方法。

在前几期文章中,已经介绍过ASM classworking 库是怎样提供了一种清洁的接口,以读取及写入二进制类。

在这篇文章中,我将向您展示如何利用ASM 从类文件中获取原始泛型信息,如何以一种有用的方式解释泛型。

在钻研ASP 细节之前,让我们首先来看看泛型信息编码到二进制类中的实际方式。

跟踪泛型为将可由Java 编译器使用的键入信息添加到Java 二进制类中,需要使用泛型规范设计器。

幸运的是,Java 平台已有一种内置于二进制类格式中的机制,可用于此目的。

这种机制就是属性结构(attribute structure),它主要使所有类型的信息可与类本身或类的方法、字段及其他组件相关联。

某些类型的属性信息是由JVM 规范定义的,但Java 语言的原始设计器作出了明智的选择,将一组可能出现的属性保留为开放,从而可由新版本的规范加以扩展,也可由用户扩展以设计其自己的自定义属性。

json 泛型解析

json 泛型解析

json 泛型解析如今,json已经成为了前端开发中最常用的数据格式。

但是,对于我们的应用程序来说,这只是他们能够使用的,我们需要将其转换成可操作的数据。

在解析json时,我们通常会将其映射到我们的应用程序模型中,这就需要用到json泛型解析。

什么是json泛型解析?泛型解析器通常是指,无论何种数据格式,都可以将其转换为特定数据类型的解析器。

JSON泛型解析器的目的是使我们的json数据适应各种数据类型并处理数据。

这些数据类型可能涵盖了整个程序块,甚至整个程序。

JSON泛型解析器的好处JSON泛型解析器的一大好处是它可以从无序的JSON数据中提取有用的信息,而无需任何外部库。

因此,如果没有安装其他任何外部库,可以很容易地实现JSON泛型解析器。

此外,泛型解析器可以轻松应用于动态类型的语言,如JavaScript。

JSON泛型解析器通常通过反射机制实现(即运行时检查类型)。

因此,它们可以适应现有的类和结构,使我们可以非常方便地将JSON数据转换为应用程序模型。

示例为了更好地理解JSON泛型解析器,让我们看一个示例。

假设我们有一个JSON字符串:{"name": "John","age": 28,"gender": "male"}我们可以定义以下模型:struct Person: Codable {let name: Stringlet age: Intlet gender: String}现在,我们可以使用以下代码将JSON字符串转换为模型:let jsonString = """{"name": "John","age": 28,"gender": "male"}"""let jsonData = jsonString.data(using: .utf8)!let decoder = JSONDecoder()let person = try decoder.decode(Person.self, from: jsonData) 在上面的代码片段中,我们使用JSONDecoder将JSON字符串转换为我们定义的Person模型。

twi工作分解表案例

twi工作分解表案例

TWiki工作分解表案例一、项目目标本项目旨在开发一款基于TWiki平台的团队协作工具,以提高团队工作效率和信息共享。

主要目标包括:1.提供一个易于使用的平台,支持团队成员之间的实时协作。

2.集成项目管理、任务跟踪、文档管理等功能,提升团队协作效率。

3.保证系统的高可用性和可扩展性,满足企业不断增长的需求。

二、任务分解为了实现项目目标,我们将任务分解为以下子任务:1.系统架构设计:设计系统整体架构,包括前端和后端的设计。

2.用户界面设计:设计易于使用的用户界面,提供良好的用户体验。

3.后端开发:开发系统后端,包括数据存储、API接口等。

4.前端开发:开发系统前端,实现用户界面交互功能。

5.插件和扩展开发:开发支持常用功能的插件和扩展。

6.系统测试:对系统进行全面测试,确保稳定性和功能性。

7.部署和维护:部署系统到生产环境,并进行持续的维护和升级。

三、责任分配为了确保项目顺利进行,我们将责任分配给以下人员:1.项目经理:负责整体项目管理和协调,包括任务分配、进度跟踪等。

2.架构师:负责系统架构设计和后端开发工作。

3.UI设计师:负责用户界面设计和前端开发工作。

4.开发人员:负责具体的开发工作,包括插件和扩展开发等。

5.测试人员:负责系统测试和缺陷跟踪工作。

6.运维人员:负责系统部署和维护工作。

四、时间计划以下是详细的时间计划:1.系统架构设计和用户界面设计(1周)2.后端开发和前端开发(4周)3.插件和扩展开发(2周)4.系统测试和缺陷跟踪(1周)5.部署和维护(1周)五、资源需求根据项目需求,以下是我们需要的资源:1.服务器资源:用于部署系统所需的基础设施资源。

2.软件资源:开发所需的编程语言、工具、库等。

3.人力资源:具有相关技能的开发、测试和运维人员。

Java中泛型ClassT、T与Class?

Java中泛型ClassT、T与Class?⼀.区别单独的T 代表⼀个类型,⽽ Class<T>代表这个类型所对应的类, Class<?>表⽰类型不确定的类E - Element (在集合中使⽤,因为集合中存放的是元素)T - Type(Java 类)K - Key(键)V - Value(值)N - Number(数值类型)? - 表⽰不确定的java类型举例说明:Set<T> 表⽰集合⾥是 T类的实例List<E> 表⽰集合⾥是 E类的实例List<?> 表⽰集合⾥的对象类型不确定,未指定List 同 List<?> 是⼀样的。

泛型的作⽤:1、⽤泛型:Java代码收藏代码List<T> list=new ArrayList<T>();T t=list.get(0);2、不⽤泛型:Java代码收藏代码List list=new ArrayList();T t=(T)list.get(0);⼆、如何创建⼀个Class<T>类型的实例?就像使⽤⾮泛型代码⼀样,有两种⽅式:调⽤⽅法 Class.forName() 或者使⽤类常量X.class。

Class.forName() 被定义为返回 Class<?>。

另⼀⽅⾯,类常量 X.class 被定义为具有类型 Class<X>,所以 String.class 是Class<String> 类型的。

三、⽅法中为什么需要<T> T修饰呢泛型的声明,必须在⽅法的修饰符(public,static,final,abstract等)之后,返回值声明之前。

public static <T> T request2Bean(HttpServletRequest request,Class<T> clazz){}其中第⼀个<T>是与传⼊的参数Class<T>相对应的,相当于返回值的⼀个泛型,后⾯的T是返回值类型,代表⽅法必须返回T类型的(由传⼊的Class<T>决定)。

Java泛型的用法及T.class的获取过程解析

Java泛型的⽤法及T.class的获取过程解析这篇⽂章主要介绍了Java泛型的⽤法及T.class的获取过程解析,⽂中通过⽰例代码介绍的⾮常详细,对⼤家的学习或者⼯作具有⼀定的参考学习价值,需要的朋友可以参考下胡乱总结泛型的四点作⽤:第⼀是泛化,可以拿个T代表任意类型。

但GP是被C++严苛的静态性逼出来的,落到Java、C#这样的花语平原⾥----所有对象除⼏个原始类型外都派⽣于Object,再加上Java的反射功能,Java的Collection库没有范型⼀样过得好好的。

第⼆是泛型 + 反射,原本因为Java的泛型拿不到T.class⽽觉得泛型没⽤,最近才刚刚学到通过反射的API来获取T的Class,后述。

第三是收敛,就是增加了类型安全,减少了强制类型转换的代码。

这点倒是Java Collection历来的弱项。

第四是可以在编译期搞很多东西,⽐如MetaProgramming。

但除⾮能完全封闭于框架内部,框架的使⽤者和扩展者都不⽤学习这些东西的⽤法,否则那就是⾃绝于⼈民的票房毒药。

C++的MetaProgramming好厉害吧,但对⽐⼀下Python拿Meta Programming⽣造⼀个Class出来的简便语法,就明⽩什么才是真正的叫好⼜叫座。

所以,作为⼀个架构设计师,应该使⽤上述的第2,3项⽤法,在框架类⾥配合使⽤反射和泛型,使得框架的能⼒更强;同时采⽤收敛特性,本着对⼈民负责的精神,⽤泛型使框架更加类型安全,更少强制类型转换。

擦拭法避免了Java的流⾎分裂:⼤家经常骂Java GP的擦拭法实现,但我觉得多亏于它的中庸特性---如果你⽤就是范型,不⽤就是普通Object,避免了Java阵营⼜要经历⼀场to be or not to be的分裂。

最⼤的例⼦莫过Java 5的Collection 框架,⽐如有些同学坚持认为⾃⼰不会⽩痴到类型出错,⽽且难以忍受每个定义的地⽅都要带⼀个泛型定义List〈Book〉,不⽤强制类型转换所省下的代码还不够N处定义花的(对了,java⾥⾯还没有tyepdef.....),因此对范型⼗分不感冒,这时就要齐齐感谢这个搽拭法让你依然可以对⼀个泛型框架保持⾮泛型的⽤法了...<<⼲货来了>>通过反射获得 T.class:abstract public class BaseHibernateEntityDao<T> extends HibernateDaoSupport {private Class<T> entityClass;public BaseHibernateEntityDao() {entityClass =(Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];} public T get(Serializable id) { T o = (T) getHibernateTemplate().get(entityClass, id); return o; } }重点就是这句话:Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];解释:1. public Type getGenericSuperclass()⽤来返回表⽰当前Class 所表⽰的实体(类、接⼝、基本类型或 void)的直接超类的Type。

tabbycat 包:分类变量的汇总和汇总说明书

Package‘tabbycat’August22,2023Type PackageTitle Tabulate and Summarise Categorical DataVersion0.18.0Maintainer Oliver Hawkins<******************>Description Functions for tabulating and summarising categorical variables.Most functions are designed to work with dataframes,and use the'tidyverse'idiom of taking the dataframe as thefirst argument so they work withinpipelines.Equivalent functions that operate directly on vectors are alsoprovided where it makes sense.This package aims to make exploratory dataanalysis involving categorical variables quicker,simpler and more robust.License MIT+file LICENSEDepends R(>=3.4.0)Imports dplyr(>=1.0.0),janitor,magrittr,purrr,rlang,stringr,tibble,tidyrEncoding UTF-8RoxygenNote7.2.3Suggests testthat(>=3.0.0)Config/testthat/edition3NeedsCompilation noAuthor Oliver Hawkins[aut,cre]Repository CRANDate/Publication2023-08-2219:30:02UTCR topics documented:cat_compare (2)cat_contrast (3)cat_count (4)cat_summarise (5)cat_vcount (6)Index812cat_compare cat_compare Calculate the frequency of discrete values in one categorical variablefor each group within another categorical variableDescriptionThis function crosstabulates the frequencies of one categorical variable within the groups of another.The results are sorted on the values of the variable whose distribution is shown in each columni.e.the variable specified with row_cat.If this variable is a character vector it will be sortedalphabetically.If it is a factor it will be sorted in the order of its levels.Usagecat_compare(data,row_cat,col_cat,na.rm.row=FALSE,na.rm.col=FALSE,na.rm=NULL,only="",clean_names=getOption("tabbycat.clean_names"),na_label=getOption("tabbycat.na_label"))Argumentsdata A dataframe containing the two variables of interest.row_cat The column name of a categorical variable whose distribution will be calculated for each group in col_cat.col_cat The column name of a categorical variable which will be split into groups and the distrubtion of row_cat calulated for each group.na.rm.row A boolean indicating whether to exclude NAs from the row results.The default is FALSE.na.rm.col A boolean indicating whether to exclude NAs from the column results.The default is FALSE.na.rm A boolean indicating whether to exclude NAs from both row and column results.This argument is provided as a convenience.It allows you to set na.rm.row andna.rm.col to the same value without having to specify them separately.If thevalue of na.rm is NULL,the argument is ignored.If it is not NULL it takesprecendence.default is NULL.only A string indicating that only one set of frequency columns should be returned in the results.If only is either"n"or"number",only the number columns are re-turned.If only is either"p"or"percent",only the percent columns are returned.If only is any other value,both sets of columns are shown.The default value isan empty string,which means both sets of columns are shown.cat_contrast3 clean_names A boolean indicating whether the column names of the results tibble shouldbe cleaned,so that any column names produced from data are converted tosnake_case.The default is TRUE,but this can be changed with options(tabbycat.clean_names=FALSE).na_label A string indicating the label to use for the columns that contain data for missingvalues.The default value is"na",but use this argument to set a different value ifthe default value collides with data in your dataset.ValueA tibble showing the distribution of row_cat within each group in col_cat.cat_contrast Calculate the frequency of discrete values in one categorical variablefor each of two mutually exclusive groups within another categoricalvariableDescriptionThis function shows the distrbution of values within given a categorical variable for one groupwithin another categorical variable,and compares it with the distribution among all observationsnot in that group.Its purpose is to let you see quickly whether the distribution within that groupdiffers from the distribution for the rest of the observations.The results are sorted in descendingorder of frequency for the named group i.e.the group named in col_group.Usagecat_contrast(data,row_cat,col_cat,col_group,na.rm.row=FALSE,na.rm.col=FALSE,na.rm=NULL,only="",clean_names=getOption("tabbycat.clean_names"),na_label=getOption("tabbycat.na_label"),other_label=getOption("tabbycat.other_label"))Argumentsdata A dataframe containing the two variables of interest.row_cat The column name of a categorical variable whose distribution should be calcu-lated for each exclusive group in col_cat.4cat_count col_cat The column name of a categorical variable that will be split into two exclusivegroups,one containing observations with a particular value of that variable,andanother containing all other observations.col_group The name of the group within col_cat that is used to split the observations intotwo exclusive groups:those that are in the group and those that are not in thegroup.na.rm.row A boolean indicating whether to exclude NAs from the row results.The defaultis FALSE.na.rm.col A boolean indicating whether to exclude NAs from the column results.Thedefault is FALSE.na.rm A boolean indicating whether to exclude NAs from both row and column results.This argument is provided as a convenience.It allows you to set na.rm.row andna.rm.col to the same value without having to specify them separately.If thevalue of na.rm is NULL,the argument is ignored.If it is not NULL it takesprecendence.default is NULL.only A string indicating that only one set of frequency columns should be returned inthe results.If only is either"n"or"number",only the number columns are re-turned.If only is either"p"or"percent",only the percent columns are returned.If only is any other value,both sets of columns are shown.The default value isan empty string,which means both sets of columns are shown.clean_names A boolean indicating whether the column names of the results tibble shouldbe cleaned,so that any column names produced from data are converted tosnake_case.The default is TRUE,but this can be changed with options(tabbycat.clean_names=FALSE).na_label A string indicating the label to use for the columns that contain data for missingvalues.The default value is"na",but use this argument to set a different value ifthe default value collides with data in your dataset.other_label A string indicating the label to use for the columns that contain data for observa-tions not in the named group.The default value is"other",but use this argumentto set a different value if the default value collides with data in your dataset.ValueA tibble showing the distribution of row_cat within each of the two exclusive groups in col_cat.cat_count Count the frequency of discrete values in the column of a dataframeDescriptionThis function differs from cat_vcount in that it operates on columns in dataframes rather thandirectly on vectors,which means it is more useful in pipelines but handles a narrower range ofinputs.The results are sorted in descending order of frequency.cat_summarise5Usagecat_count(data,cat,na.rm=FALSE,only="",clean_names=getOption("tabbycat.clean_names"))Argumentsdata A dataframe containing a categorical vector for which frequencies will be cal-culated.cat The column name of the categorical variable for which frequencies will be cal-culated.na.rm A boolean indicating whether to exclude NAs from the results.The default isFALSE.only A string indicating that only one of the frequency columns should be returnedin the results.If only is either"n"or"number",only the number column isreturned.If only is either"p"or"percent",only the percent column is returned.If only is any other value,both columns are shown.The default value is anempty string,which means both columns are shown.clean_names A boolean indicating whether the column names of the results tibble shouldbe cleaned,so that any column names produced from data are converted tosnake_case.The default is TRUE,but this can be changed with options(tabbycat.clean_names=FALSE).ValueA tibble showing the frequency of each value in cat.cat_summarise Summarise the values of a numerical variable for each group within acategorical variableDescriptionThe results are sorted on the values of the categorical variable i.e.the variable specified with cat.If this variable is a character vector it will be sorted alphabetically.If it is a factor it will be sortedin the order of its levels.This function can be called as either cat_summarise or cat_summarize.Usagecat_summarise(data,cat,num,na.rm=FALSE,clean_names=getOption("tabbycat.clean_names"))cat_summarize(data,cat,num,na.rm=FALSE,clean_names=getOption("tabbycat.clean_names"))Argumentsdata A dataframe containing a categorical variable and numerical variable to sum-marise.cat The name of a column in data which is a categorical vector of discrete valuesfor which summaries will be calculated.num The name of a column in data which is a numerical vector that will be sum-marised for each group.na.rm A boolean indicating whether to exclude NAs from the row results.Note thatNAs are**always**ignored in calculating the summary statistics for num shownin each row,and the number of NAs that exist in num for each group in cat isshown in the na column of the results table.This argument controls whether arow of summary statistics is shown for observations that are NA in cat.Thedefault is FALSE.clean_names A boolean indicating whether the column names of the results tibble shouldbe cleaned,so that any column names produced from data are converted tosnake_case.The default is TRUE,but this can be changed with options(tabbycat.clean_names=FALSE).ValueA tibble showing summary statistics for num for each group in cat.cat_vcount Count the frequency of discrete values in a categorical vectorDescriptionThis function differs from cat_count in that it operates directly on vectors,rather than on columnsin dataframes,which means it is less useful in pipelines but can handle a wider range of inputs.Theresults are sorted in descending order of frequency.Usagecat_vcount(cat,na.rm=FALSE,only="",clean_names=getOption("tabbycat.clean_names"))Argumentscat A categorical vector for which frequencies will be calculated.na.rm A boolean indicating whether to exclude NAs from the results.The default isFALSE.only A string indicating that only one of the frequency columns should be returnedin the results.If only is either"n"or"number",only the number column isreturned.If only is either"p"or"percent",only the percent column is returned.If only is any other value,both columns are shown.The default value is anempty string,which means both columns are shown.clean_names A boolean indicating whether the column names of the results tibble shouldbe cleaned,so that any column names produced from data are converted tosnake_case.The default is TRUE,but this can be changed with options(tabbycat.clean_names=FALSE).ValueA tibble showing the frequency of each value in cat.Indexcat_compare,2cat_contrast,3cat_count,4cat_summarise,5cat_summarize(cat_summarise),5cat_vcount,68。

如何在C#中高效地搜索泛型集合

如何在C#中⾼效地搜索泛型集合例如,假设我们有两个内存集合,⼀个集合包含City 模型,另⼀个集合包含Restaurant 模型。

我们的系统需要按City 组织 Restaurant :这是我们的模型,其中Restaurant的CityId属性⽤于标识其居住的City:1public class City2 {3public Guid Id { get; set; }4public string Name { get; set; }5 }67public class Restaurant8 {9public Guid Id { get; set; }10public Guid CityId { get; set; }11public string Name { get; set; }12 }我们的⽬标是优化组织集合的操作。

为了做到这⼀点,我们必须确保对内存中的集合进⾏尽可能少的迭代。

⾸先让我们看⼀下效率低下的解决⽅案,并讨论如何对其进⾏改进。

1public IDictionary<City, IEnumerable<Restaurant>> OrganizeRestaurantsByCity(IEnumerable<City> cities, IEnumerable<Restaurant> restaurants)2 {3 IDictionary<City, IEnumerable<Restaurant>> restaurantsByCity = new Dictionary<City, IEnumerable<Restaurant>>();45foreach (var city in cities)6 {7var restaurantsInCity = restaurants8 .Where(restaurant => restaurant.CityId.Equals(city.Id));910 restaurantsByCity.Add(city, restaurantsInCity);11 }1213return restaurantsByCity;14 }⾸先,我们实例化⼀个以City为关键字的字典,每个关键字都指向⼀组Restaurant 。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档