精华内容
下载资源
问答
  • 这周接到一个活,因为某个课题研究需要,须把脑卒中患者的名单和一份健康人(对照)名单按照”性别相同,乡镇地址相同,年龄相差3岁以内“作为匹配条件进行1:1的匹配,现将思考及实现的过程逐一记录并在此分享,希望...

    这周接到一个活,因为某个课题研究需要,须把脑卒中患者的名单和一份健康人(对照)名单按照”性别相同,乡镇地址相同,年龄相差3岁以内“作为匹配条件进行1:1的匹配,现将思考及实现的过程逐一记录并在此分享,希望能给大家有所借鉴与帮助。

    拿到这份数据后首要的工作是熟悉数据和提取关键信息。这两份数据都是保存于Excel中的单表结构的数据(没有复杂的表关联),脑卒中患者1300多条,健康人8200多条,做1:1匹配绰绰有余;主索引采用身份证号,关键信息有”姓名、性别、年龄和乡镇地址“。然后考虑输出的结果的格式,Excel,表单中列入脑卒中患者的全部数据,最后增加一列存放匹配的对照者身份证号。

    接下来开始动手编程,第一步引用pandas导入数据。其中路径前的"r"和中文前的"u"不可少,可能是因为我还在用Python2的关系。

    # -*- coding: gbk -*-
    #!/usr/bin/env python
    # __author__ = 'PanJin'
    
    import pandas as pd
    case=pd.read_excel(r'D:\并发症数据库(实验室检测筛选).xls',sheet_name=u'心脑')
    ctrl=pd.read_excel(r'D:\并发症数据库(实验室检测筛选).xls',sheet_name=u'对照(不包含肿瘤)')
    

    动手分析之前一直有个担心,作为索引的身份证号是否会有重复的记录,果然我的担心应验了,查重发现健康个案的身份证号有4组是重复的(在Excel里用公式查的,所以没有上代码),同时发现8000多人中有部分因为失访,检查结果有大量缺失,于是和重复的身份证号进行了删除。(代码中的身份证号进行了脱敏处理)

    ctrl_=ctrl[(ctrl.sfzh !='33042119320221####') & (ctrl.sfzh !='33072219560522####') & (ctrl.sfzh !='33042119381031####') & (ctrl.sfzh !='33042119390824####') & (ctrl.HDLC2 !='#NULL!')]
    

    刚开始打算用pandas里的merge直接解决战斗的,但是发现问题想的太简单了,因为根据匹配条件”性别相同,乡镇地址相同,年龄相差3岁以内“,直接merge的结果一定会有很多一对多甚至多对多的笛卡尔积产生,而对这些笛卡尔积好像没有太好的自动化处理方案,因此我在开始就放弃了这种尝试。所以我的计划是采用Python里的for循环来解决。

    解题思路如下:

    首先从脑卒中患者清单中取第一条,在健康对照中按条件匹配所有适合的名单,然后取第一条(或者调用random函数来随机一下),已匹配的健康对照从大名单中删除,然后进行再取第二条脑卒中患者重复以上过程直至循环到最后。最终将形成3个名单,1.匹配完成名单;2.患者未匹配名单;3.健康对照未匹配名单。

    另外考虑匹配优化的问题,我把这个循环分成了两轮,第一轮中匹配条件为”性别相同,乡镇地址相同,年龄相等“,第二轮中为”性别相同,乡镇地址相同,年龄相差3岁以内“,这样能保证条件接近的健康对象优先进入匹配。

    接下来是实现的步骤:

    首先确定能取到数据库里的目标值,这个步骤很重要,Python中取值是件很头疼的事情,数据格式有很多种,在Pandas里有DataFrame、Series,另外还有list、object等格式,只时候看起来是一个单个的值,但是却不能直接做比较,因此通过取值调试,可以发现并处理很多编码过程中的错误。

    name=case['name'].values[0]
    sfzh=case['sfzh'].values[0]
    sex=case['sex'].values[0]
    age=case['age'].values[0]
    xz=case['xz'].values[0]
    # 取值
    In[1]
    print name
    print sfzh
    print sex
    print age
    print xz
    
    Out[1]
    蒋*英
    3304211941########
    2
    75
    西塘

    按照以上的取值,在对照中寻找匹配记录。

    In[2]
    print ctrl_[(ctrl_.sex==2) & (ctrl_.age==age) & (ctrl_.xz==xz)]
    Out[2]
    
         area name                sfzh  ...   GLU2   TC2  LDLC2
    1115   js  吕*英  3304111941########  ...      0     5      2
    2039   js  彭*花  3304211941########  ...      0  3.74   1.52
    ...
    7028   js  孔*花  3304211941########  ...      0  4.21   1.75
    
    [9 rows x 43 columns]
    

    将具体值替换为代码,同时取第一条匹配记录,并对身份证号取值。

    In[3]
    print ctrl_[(ctrl_.sex==case['sex'].values[0]) & (ctrl_.age==case['age'].values[0]) & (ctrl_.xz==case['xz'].values[0])]['sfzh'].values[0]
    Out[3]
    3304111941########

    取值成功后,进入For循环的编写。迭代变量设定为i,在case.index范围内进行,逐条取脑卒中患者记录,通过之前的取值程序算出匹配对照的身份证号,写入该患者记录最后一个字段,然后放入case_match中,匹配过的对照按照身份证号从ctrl_里删去。为了调试过程中能看到每一步产出的结果,对temp和aa两个中间变量进行了print。具体代码如下:

    case_match=case.iloc[:0]#建立空匹配库
    for i in case.index:
        temp=case.iloc[i]
        print temp
        aa=ctrl_[(ctrl_.sex==case['sex'].values[i]) & (ctrl_.age==case['age'].values[i]) & (ctrl_.xz==case['xz'].values[i])]['sfzh'].values[0]
        print aa
        temp['ctrl_sfzh']=aa
        case_match=case_match.append(temp,ignore_index=True,sort=False)#拼接匹配完成库
        ctrl_=ctrl_[ctrl_.sfzh !=aa]#删去已匹配对照记录
    

    跑的过程中发现,出现了中断,报错记录显示取到了空值,核实数据库后发现,原来是有脑卒中患者找不到合适的匹配记录。

    Traceback (most recent call last):
      File "D:/work/ʡ����/���?��߹�����Ŀ/2018��ʵ�����������/case_match.py", line 29, in <module>
        aa=ctrl_[(ctrl_.sex==case['sex'].values[i]) & (ctrl_.age==case['age'].values[i]) & (ctrl_.xz==case['xz'].values[i])]['sfzh'].values[0]
    IndexError: index 0 is out of bounds for axis 0 with size 0

    这个坎是绕不过去了,只能求助于try.....except了,try部分里放的是正常的流程,except IndexError表明报错的时候运行以下的程序,把无法匹配的脑卒中患者记录放入另外的一个库case_remain里,问题完美解决!看着一行行print的结果,真是赏心悦目啊。

    case_match=case.iloc[:0]
    case_remain=case.iloc[:0]
    for i in case.index:
        temp=case.iloc[i]
    #     print temp
        try:
            aa=ctrl_[(ctrl_.sex==case['sex'].values[i]) & (ctrl_.age==case['age'].values[i]) & (ctrl_.xz==case['xz'].values[i])]['sfzh'].values[0]
            print aa
            temp['ctrl_sfzh']=aa
            case_match=case_match.append(temp,ignore_index=True,sort=False)
            ctrl_=ctrl_[ctrl_.sfzh !=aa]
        except IndexError:
            case_remain=case_remain.append(temp,ignore_index=True,sort=False)

    有了一次的成功经验后,下一个循环就照猫画虎了,但是要注意数据库命名的时候不要重复了,引用不要出错。

    case_match2=case.iloc[:0]
    case_remain2=case.iloc[:0]
    for i in case_remain.index:
        temp=case_remain.iloc[i]
    #     print temp
        try:
            aa=ctrl_[(ctrl_.sex==case_remain['sex'].values[i]) & (abs(ctrl_.age-case_remain['age'].values[i])<=3) & (ctrl_.xz==case_remain['xz'].values[i])]['sfzh'].values[0]
            print aa
            temp['ctrl_sfzh']=aa
            case_match2=case_match2.append(temp,ignore_index=True,sort=False)
            ctrl_=ctrl_[ctrl_.sfzh !=aa]
        except IndexError:
            case_remain2=case_remain2.append(temp,ignore_index=True,sort=False)

    最后把结果导出到Excel,大功告成!!

    case_match.to_excel(r'D:\case_match.xls')
    case_match2.to_excel(r'D:\case_match2.xls')
    case_remain2.to_excel(r'D:\case_remain2.xls')
    ctrl_.to_excel(r'D:\ctrl_remain.xls')

    总结一下本次编程的体会,搞清楚任务目标后的第一步是熟悉数据库结构,找到关键及核心字段,数据的前期清理也很重要(去重、缺失值的删除/填充);然后是关键及核心字段的取值,先单条再批量,取值结果随时print,这些都是好习惯,不要怕设置中间变量,中间变量多了约容易发现问题,并不是所有人一开始都能写个一长串多重嵌套的代码的,用完的中间变量和调试程序可以用注释语句给标注掉;For循环是个好工具,try....except也能帮你解决好多问题;最后感言一下,“文章不厌百回改,代码不厌百回调”,对于刚入门和生手来说,写代码肯定是个很纠结的过程,会踩各种坑,会碰到各种报错,但解决后程序顺利跑完的成就感是无法言表的。刚开始代码长没关系,结构乱也没关系,只要能跑出需要的结果就行。每当你回头对之前写的代码各种嫌弃的时候,恭喜你的编码能力成长了!最后po整个程序的最终完成版。

    # -*- coding: gbk -*-
    #!/usr/bin/env python
    # __author__ = 'PanJin'
    
    import pandas as pd
    case=pd.read_excel(r'D:\并发症数据库(实验室检测筛选).xls',sheet_name=u'心脑')
    ctrl=pd.read_excel(r'D:\并发症数据库(实验室检测筛选).xls',sheet_name=u'对照(不包含肿瘤)')
    ctrl_=ctrl[(ctrl.sfzh !='3304211932########') & (ctrl.sfzh !='3307221956########') & (ctrl.sfzh !='3304211938########') & (ctrl.sfzh !='3304211939########') & (ctrl.HDLC2 !='#NULL!')]
    # 删除身份证号重复和检查结果缺失的记录
    
    # name=case['name'].values[1]
    # sfzh=case['sfzh'].values[1]
    # sex=case['sex'].values[1]
    # age=case['age'].values[1]
    # xz=case['xz'].values[1]
    # # 取值
    # print name
    # print sfzh
    # print sex
    # print age
    # print xz
    # print ctrl_[(ctrl_.sex==case['sex'].values[0]) & (ctrl_.age==case['age'].values[0]) & (ctrl_.xz==case['xz'].values[0])]['sfzh'].values[0]
    
    case_match=case.iloc[:0]
    case_remain=case.iloc[:0]
    for i in case.index:
        temp=case.iloc[i]
    #     print temp
        try:
            aa=ctrl_[(ctrl_.sex==case['sex'].values[i]) & (ctrl_.age==case['age'].values[i]) & (ctrl_.xz==case['xz'].values[i])]['sfzh'].values[0]
            print aa
            temp['ctrl_sfzh']=aa
            case_match=case_match.append(temp,ignore_index=True,sort=False)
            ctrl_=ctrl_[ctrl_.sfzh !=aa]
        except IndexError:
            case_remain=case_remain.append(temp,ignore_index=True,sort=False)
    
    
    case_match2=case.iloc[:0]
    case_remain2=case.iloc[:0]
    for i in case_remain.index:
        temp=case_remain.iloc[i]
    #     print temp
        try:
            aa=ctrl_[(ctrl_.sex==case_remain['sex'].values[i]) & (abs(ctrl_.age-case_remain['age'].values[i])<=3) & (ctrl_.xz==case_remain['xz'].values[i])]['sfzh'].values[0]
            print aa
            temp['ctrl_sfzh']=aa
            case_match2=case_match2.append(temp,ignore_index=True,sort=False)
            ctrl_=ctrl_[ctrl_.sfzh !=aa]
        except IndexError:
            case_remain2=case_remain2.append(temp,ignore_index=True,sort=False)
    
    case_match.to_excel(r'D:\case_match.xls')
    case_match2.to_excel(r'D:\case_match2.xls')
    case_remain2.to_excel(r'D:\case_remain2.xls')
    ctrl_.to_excel(r'D:\ctrl_remain.xls')
    

     

    转载于:https://my.oschina.net/facewall123/blog/3059514

    展开全文
  • 正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。本集小编为大家讲讲xshell中正则表达式里的pattern匹配...

           正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。本集小编为大家讲讲xshell中正则表达式里的pattern匹配。

      81e13a451c32471083af1c649e3777ff.png

      xshell下载:http://www.xshellcn.com/xiazai.html

    来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30151199/viewspace-1979432/,如需转载,请注明出处,否则将追究法律责任。

    转载于:http://blog.itpub.net/30151199/viewspace-1979432/

    展开全文
  • 遥控器型号 配遥控器 遥控器参数 各大品牌杂牌遥控器
  • 单元组,所有最终匹配的治疗单元以及所有最终匹配对照单元,不应系统地区别,以减少偏差 每对中的单位应相似,以减少差异 但是,仅评估偏倚部分的组级统计信息是不够的:说我们有一些变量x并且在我们的(已处理,...
  • Hive on Spark 互相匹配的版本对照

    千次阅读 2019-01-22 08:15:02
    Hive Version Spark Version 3.0.x 2.3.0 2.3.x 2.0.0 2.2.x 1.6.0 2.1.x 1.6.0 2.0.x 1.5.0 1.2.x 1.3.1 1.1.x 1.2.0

    Hive Version

    Spark Version

    3.0.x 2.3.0
    2.3.x 2.0.0
    2.2.x 1.6.0
    2.1.x 1.6.0
    2.0.x 1.5.0
    1.2.x 1.3.1
    1.1.x 1.2.0
    展开全文
  • 上一篇:Scala Tutorial中英对照:和Java交互,一切皆对象这个文档,是翻译自官方的Scala Tutorial ,为了防止自己理解错误,保留原文以便参照。由于篇幅所限,共分成三篇。博客中格式不好调整,感兴趣的朋友可以...

    上一篇:Scala Tutorial中英对照:和Java交互,一切皆对象

    这个文档,是翻译自官方的Scala Tutorial ,为了防止自己理解错误,保留原文以便参照。

    由于篇幅所限,共分成三篇。

    博客中格式不好调整,感兴趣的朋友可以下载PDF版本:http://download.csdn.net/source/1742639

    ---

    6条件类和模式匹配 Case classes and pattern matching

    树是软件开发中使用频率很高的一种数据结构,例如:解释器和编译器内部使用树来表示代码结构;XML文档是树形结构;还有一些容器(集合,containers)也是基于树的,比如:红黑树(red-black tree,一种自平衡二叉查找树)。

    A kind of data structure that often appears in programs is the tree. For example, interpreters and compilers usually represent programs internally as trees; XML documents are trees; and several kinds of containers are based on trees, like red-black trees.

    接下来,我们通过一个示例程序,了解在Scala中如何表示和操作树形结构,这个示例将实现非常简单的计算器功能,该计算器可以处理包含加法、变量和整数常量的算术表达式,比如:1 + 2、(x + x) + (7 + y)等。

    We will now examine how such trees are represented and manipulated in Scala through a small calculator program. The aim of this program is to manipulate very simple arithmetic expressions composed of sums, integer constants and variables. Two examples of such expressions are 1 + 2 and (x + x) + (7 + y).

    首先,我们要决定如何表示这样的表达式。最自然的选择是树形结构,用非叶子节点表示操作符(具体到这个例子,只有 加法操作),用叶子节点表示操作数(具体到这个例子是常量和变量)。

    We first have to decide on a representation for such expressions. The most natural one is the tree, where nodes are operations (here, the addition) and leaves are values (here constants or variables).

    如果是在Java中,建立树形结构最常见的做法是:创建一个表示树的抽象类,然后每种类型的节点用一个继承自抽象类的子类来表示。而在函数式编程语言中,则可以使用代数数据类型(algebraic data-type)来达到同样的目的。Scala则提供了一种介于两者之间(类继承和代数数据类型),被称为条件类(case classes)的概念,下面就是用条件类定义树的示例代码:

    In Java, such a tree would be represented using an abstract super-class for the trees, and one concrete sub-class per node or leaf. In a functional programming language, one would use an algebraic data-type for the same purpose. Scala provides the concept of case classes which is somewhat in between the two. Here is how they can be used to define the type of the trees for our example:

    abstract class Tree

    case class Sum(l: Tree, r: Tree) extends Tree

    case class Var(n: String) extends Tree

    case class Const(v: Int) extends Tree

    上例中的Sum, Var和Const就是条件类,它们与普通类的差异主要体现在如下几个方面:

    The fact that classes Sum, Var and Const are declared as case classes means that they differ from standard classes in several respects:

    ·   新建条件类的实例,无须使用new关键字(比如,可以直接用Const(5)代替new Const(5)来创建实例)。

    ·   the new keyword is not mandatory to create instances of these classes (i.e. one can write Const(5) instead of new Const(5)),

    ·   自动为构造函数所带的参数创建对应的getter方法(也就是说,如果c是Const的实例,通过c.v即可访问构造函数中的同名参数v的值)

    ·   getter functions are automatically defined for the constructor parameters (i.e. it is possible to get the value of the v constructor parameter of some instance c of class Const just by writing c.v),

    ·   条件类都默认实现equals和hashCode两个方法,不过这两个方法都是基于实例的结构本身(structure of instance),而不是基于实例中可用于区分的值(identity),这一点和java中Object提供的同名方法的默认实现是基本一致的。

    ·   default definitions for methods equals and hashCode are provided, which work on the structure of the instances and not on their identity,

    ·   条件类还提供了一个默认的toString方法,能够以源码形式(source form)打印实例的值(比如,表达式x+1会被打印成Sum(Var(x),Const(1)),这个打印结果,和源代码中创建表达式结构树的那段代码完全一致)。

    ·   a default definition for method toString is provided, and prints the value in a “source form” (e.g. the tree for expression x+1 prints as Sum(Var(x),Const(1))),

    ·   条件类的实例可以通过模式匹配(pattern matching)进行分解(decompose),接下来会详细介绍。

    ·   instances of these classes can be decomposed through pattern matching as we will see below.

    既然我们已经定义了用于表示算术表达式的数据结构,接下来我们可以定义作用在这些数据结构上的操作。首先,我们定义一个在特定环境(environment,上下文)中对表达式进行求值的函数,其中环境的作用是为了确定表达式中的变量的取值。例如:有一个环境,对变量x的赋值为5,我们记为:{x → 5},那么,在这个环境上求x + 1的值,得到的结果为6。

    Now that we have defined the data-type to represent our arithmetic expressions, we can start defining operations to manipulate them. We will start with a function to evaluate an expression in some environment. The aim of the environment is to give values to variables. For example, the expression x + 1 evaluated in an environment which associates the value 5 to variable x, written {x → 5}, gives 6 as result.

    在程序中,环境也需要一种合理的方式来表示。可以使用哈希表(hash table)之类的数据结构,也可以直接使用函数(functions)!实际上,环境就是一个给变量赋予特定值的函数。上面提到的环境:{x → 5},在Scala中可以写成:

    We therefore have to find a way to represent environments. We could of course use some associative data-structure like a hash table, but we can also directly use functions! An environment is really nothing more than a function which associates a value to a (variable) name. The environment {x → 5} given above can simply be written as follows in Scala:

    { case "x" => 5 }

    上面这一行代码定义了一个函数,如果给该函数传入一个字符串"x"作为参数,则函数返回整数5,否则,将抛出异常。

    This notation defines a function which, when given the string "x" as argument, returns the integer 5, and fails with an exception otherwise.

    在写表达式求值函数之前,我们还要对环境的类型(type of the environments)进行命名。虽然在程序中全都使用String => Int这种写法也可以的,但给环境起名后,可以简化代码,并使得将来的修改更加方便(这里说的环境命名,简单的理解就是宏,或者说是自定义类型)。在Scala中,使用如下代码来完成命名:

    Before writing the evaluation function, let us give a name to the type of the environments. We could of course always use the type String => Int for environments, but it simplifies the program if we introduce a name for this type, and makes future changes easier. This is accomplished in Scala with the following notation:

    type Environment = String => Int

    此后,类型名Environment可以作为“从String转成Int”这一类函数的别名。

    From then on, the type Environment can be used as an alias of the type of functions from String to Int.

    现在,我们来写求值函数。求值函数的实现思路很直观:两个表达式之和(sum),等于分别对两个表达式求值然后求和;变量的值直接从环境中获取;常量的值等于常量本身。在Scala中描述这个概念并不困难:

    We can now give the definition of the evaluation function. Conceptually, it is very simple: the value of a sum of two expressions is simply the sum of the value of these expressions; the value of a variable is obtained directly from the environment; and the value of a constant is the constant itself. Expressing this in Scala is not more difficult:

    def eval(t: Tree, env: Environment): Int = t match {

    case Sum(l, r) => eval(l, env) + eval(r, env)

    case Var(n) => env(n)

    case Const(v) => v

    }

    求值函数的工作原理是对树t上的结点进行模式匹配,下面是对匹配过程的详细描述(实际上是递归):

    This evaluation function works by performing pattern matching on the tree t. Intuitively, the meaning of the above definition should be clear:

    1. 求值函数首先检查树t是不是一个求和(Sum),如果是,则把t的左子树和右子树分别绑定到两个新的变量l和r上,然后对箭头右边的表达式进行运算(实际上就是分别求左右子树的值然后相加,这是一个递归)。箭头右边的表达式可以使用箭头左边绑定的变量,也就是l 和 r。it first checks if the tree t is a Sum, and if it is, it binds the left sub-tree to a new variable called l and the right sub-tree to a variable called r, and then proceeds with the evaluation of the expression following the arrow; this expression can (and does) make use of the variables bound by the pattern appearing on the left of the arrow, i.e. l and r,

    2. 如果第一个检查不满足,也就是说,树t不是Sum,接下来就要检查t是不是一个变量Var;如果是,则Var中包含的名字被绑定到变量n上,然后继续执行箭头右边的逻辑。if the first check does not succeed, that is if the tree is not a Sum, it goes on and checks if t is a Var; if it is, it binds the name contained in the Var node to a variable n and proceeds with the right-hand expression,

    3. 如果第二个检查也不满足,那意味着树t既不是Sum,也不是Var,那就进一步检查t是不是常量Const。如果是,则将常量所包含的值赋给变量v,然后继续执行箭头右边的逻辑。if the second check also fails, that is if t is neither a Sum nor a Var, it checks if it is a Const, and if it is, it binds the value contained in the Const node to a variable v and proceeds with the right-hand side,

    4. 最后,如果以上所有的检查都不满足,程序会抛出异常,表明对表达式做模式匹配时产生了错误。这种情况,在本例中,只有声明了更多Tree的子类,却没有增加对应的模式匹配条件时,才会出现。finally, if all checks fail, an exception is raised to signal the failure of the pattern matching expression; this could happen here only if more sub-classes of Tree were declared.

    通过上例,我们可以看到,模式匹配的过程,实际上就是把一个值(value)和一系列的模式进行比对,如果能够匹配上,则从值(value)中取出有用的部件(parts)进行命名,然后用这些命名的部件(作为参数)来驱动另一段代码的执行。

    We see that the basic idea of pattern matching is to attempt to match a value to a series of patterns, and as soon as a pattern matches, extract and name various parts of the value, to finally evaluate some code which typically makes use of these named parts.

    一个有经验(seasoned,老练的)的面向对象程序员可能会问:为什么不把eval定义成类Tree的成员方法?事实上,这么做也行,因为在Scala中,条件类和普通类一样,都可以定义方法。不过,“模式匹配”和“类方法”除了编程风格的差异,也各有利弊,决策者需要根据程序的扩展性需求做出权衡和选择:

    A seasoned object-oriented programmer might wonder why we did not define eval as a method of class Tree and its subclasses. We could have done it actually, since Scala allows method definitions in case classes just like in normal classes. Deciding whether to use pattern matching or methods is therefore a matter of taste, but it also has important implications on extensibility:

    ·   使用类方法,添加一种新的节点类型比较简单,因为只需要增加一个Tree的子类即可。但是,要在树上增加一种新的操作则比较麻烦,因为这需要修改Tree的所有子类。

    ·   when using methods, it is easy to add a new kind of node as this can be done just by defining the sub-class of Tree for it; on the other hand, adding a new operation to manipulate the tree is tedious, as it requires modifications to all sub-classes of Tree,

    ·   使用模式匹配,情况则刚好相反:增加一种新的节点类型需要修改所有作用在树上的模式匹配函数;而增加新的操作则比较简单,只需要增加一个新的函数即可。

    ·   when using pattern matching, the situation is reversed: adding a new kind of node requires the modification of all functions which do pattern matching on the tree, to take the new node into account; on the other hand, adding a new operation is easy, by just defining it as an independent function.

    为了更深入的探索模式匹配,我们要在算术表达式上定义一个新的操作:对符号求导(symbolic derivation,导数)。该操作的规则如下:

    To explore pattern matching further, let us define another operation on arithmetic expressions: symbolic derivation. The reader might remember the following rules regarding this operation:

    1. 对和求导,等于分别求导的和。the derivative of a sum is the sum of the derivatives,

    2. 对变量v求导,有两种情况:如果变量v正好是用于求导的符号,则返回1,否则返回0。the derivative of some variable v is one if v is the variable relative to which the derivation takes place, and zero otherwise,

    3. 常量求导恒为0。the derivative of a constant is zero.

    这几条规则几乎可以直接翻译成Scala的代码:

    These rules can be translated almost literally into Scala code, to obtain the following definition:

    def derive(t: Tree, v: String): Tree = t match {

    case Sum(l, r) => Sum(derive(l, v), derive(r, v))

    case Var(n) if (v == n) => Const(1)

    case _ => Const(0)

    }

    通过求导函数的定义,又引出了两个跟模式匹配相关的知识点。第一、case语句可以带一个guard,它由关键字if和紧随其后的表达式组成。guard的作用是对case匹配的模式进行二次限定,只有if后面的表达式为true时,才允许匹配成功。在本例中,guard保证当且仅当被求导的变量名n等于当前求导符号v时,才返回常量1。第二、模式匹配中可以使用通配符(记为_,下划线)来匹配任意值(相当于java中switch语句的default分支)。

    This function introduces two new concepts related to pattern matching. First of all, the case expression for variables has a guard, an expression following the if keyword. This guard prevents pattern matching from succeeding unless its expression is true. Here it is used to make sure that we return the constant 1 only if the name of the variable being derived is the same as the derivation variable v. The second new feature of pattern matching used here is the wild-card, written _, which is a pattern matching any value, without giving it a name.

    模式匹配的功能非常强大,但限于本文的长度和定位,我们将不再做太多深入的讨论,接下来,我们还是通过一个实例,来看看前面定义的两个函数如何使用吧。为此,我们编写一个的main函数,在函数中,先创建一个表达式:(x + x) + (7 + y),然后在环境{x → 5, y → 7}上求表达式的值,最后分别求表达式相对于xy的导数。

    We did not explore the whole power of pattern matching yet, but we will stop here in order to keep this document short. We still want to see how the two functions above perform on a real example. For that purpose, let’s write a simple main function which performs several operations on the expression (x + x) + (7 + y): it first computes its value in the environment {x → 5, y → 7}, then computes its derivative relative to x and then y.

    def main(args: Array[String]) {

    val exp: Tree = Sum(Sum(Var("x"),Var("x")),Sum(Const(7),Var("y")))

    val env: Environment = { case "x" => 5 case "y" => 7 }

    println("Expression: " + exp)

    println("Evaluation with x=5, y=7: " + eval(exp, env))

    println("Derivative relative to x:/n " + derive(exp, "x"))

    println("Derivative relative to y:/n " + derive(exp, "y"))

    }

    执行这段程序,我们得到的输出如下:

    Executing this program, we get the expected output:

    Expression: Sum(Sum(Var(x),Var(x)),Sum(Const(7),Var(y))) Evaluation with x=5, y=7: 24

    Derivative relative to x:

    Sum(Sum(Const(1),Const(1)),Sum(Const(0),Const(0))) Derivative relative to y:

    Sum(Sum(Const(0),Const(0)),Sum(Const(0),Const(1)))

    仔细观察程序的输出,我们发现,如果把求导结果化简(simplification)后再展示给用户会更好。使用模式匹配来定义一个化简函数是很有意思(同时也很棘手)的事情,读者可以自己做做练习。

    By examining the output, we see that the result of the derivative should be simplified before being presented to the user. Defining a basic simplification function using pattern matching is an interesting (but surprisingly tricky) problem, left as an exercise for the reader.

    展开全文
  • Bash字符串处理(与Java对照) - 21.字符串正则匹配 In Java 正则表达式查询 String.matches方法 boolean matches(String regex)  通知此字符串是否匹配给定的正则表达式。 String str = "...
  • 采集的数据中,企业注册地址往往都是城市名,如果你想知道这些企业分布的省份,那么就需要这样一张对照表。 文件存储位置: 百度网盘链接: https://pan.baidu.com/s/1T8aobyzXRRvDQ0NjcEBCUw 提取码: cm7g 以下是...
  • 3.3 匹配方式

    2021-05-11 21:16:18
    匹配样本的分析可以模仿RCT:可以直接比较匹配样本中治疗组和对照组的结果。在RCT的背景下,人们期望平均而言,治疗组和对照组之间的协变量分布相似。因此,当使用观察数据估计治疗效果时,可以使...
  • tensorflow API新旧对照表,修改了tensorflow 2.0以前版本的api 和2.0版本的匹配问题。对照表很详细。
  • 字号对照样张,榜数与字号匹配精确无误,印刷非常实用
  • ASCII字符串形成 :globe_with... 每个字符的ASCII值递增,并对照给定的字符串进行检查。 一直执行此过程,直到获得所形成字符串的所有字符都与给定字符串匹配为止。 语: Java 输入: 特点。 高度(5,10,15,...)。
  • 1、关于最大匹配的用途 ...最大匹配的思想可以理解为在遍历句子的过程中比较子串与对照集(词典)是否一致。子串指的是我们按照一定的长度从句子中得到的字符串,将得到的字符串与对照集一一比...
  • 本资源是身份证号籍贯对照表,记录了全国籍贯对照信息,用于核对身份证信息对应的地址,一般用与查找匹配用,切勿用于非法途径
  • 倾向匹配得分PSM学习笔记

    千次阅读 多人点赞 2020-07-15 11:47:49
    一直在想写倾向匹配得分PSM学习笔记,好好总结一下。但一直拖着,对倾向匹配得分法虽然思想比较理解,但没有系统地学习,所以这篇博客总结一下老师们的一些文章,在总结中学习,哈哈~ 1 产生背景 参考学习文章:...
  • PSM倾向匹配详细步骤和程序

    千次阅读 2020-09-12 01:17:37
    4.2试验组可匹配的观测概览,按照命令中设定的匹配规则,试验组有8例患者未能匹配到合适对照。4.3结果解读的重点应该是对stata新生成的中间变量的解读。4.4均衡性检验结果4.5匹配结果的图示化5.Stata命令汇总最后...
  • 正则表达式对照

    2019-10-08 01:17:22
    正则各字符含义 ...串行“\\”匹配“\”而“\(”则匹配“(”。 ^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。 $ 匹配输入字符串的结...
  • JDK版本与major.minor version的对照关系

    万次阅读 2018-02-26 17:29:43
    在开发中,经常会遇到类似Unsupported major.minor version 51.0的错误,一般情况下都是JDK版本不匹配造成的。 这里将JDK版本和major.minor的版本的对照关系进行整理,作为今后查阅的依据。 序号 jdk版本 ...
  • 直方图匹配的数学原理

    万次阅读 多人点赞 2018-04-22 14:17:48
    与直方图均衡化有密切的联系,建议看明白直方图均衡化(参考博主的另一篇博客直方图均衡化的数学原理),再看直方图匹配,文中图像截取自数字图像处理-冈萨雷斯-第三版,该书翻译一般,可以中英文对照。 注意:仔细...
  • 猫眼电影动态字体进行解密,反反爬,成功获取真实数据。自动对照字体文件,形成字典,无需自己匹配
  • 通常来说动物的物理年龄与其生理年龄是不匹配的,如果要严格的根据动物的生理年龄排序需要有一个具体的参照(例如人)。下面列出了狗和人以及猫和人的年龄对照表。 狗 1 2 3 ...
  • 在实现基于网络语料库和双语网页搜索的辅助翻译系统的过程中,利用网络机器人从互联网上获取中英文双语对照网页,对它们进行过滤,留下有用的信息,再把中英文句子进行匹配存人数据库。分句匹配算法是语言翻译处理领域的...
  • 2019 Selenium Chrome版本与chromedriver兼容版本对照

    万次阅读 多人点赞 2018-06-05 13:51:59
    在使用selenium启动谷歌Chrome浏览器的时候,是需要用到chromedirver的,两者之间的版本是需要匹配的,否则会出现下面类似的报错: Exception in thread "main" org.openqa.selenium.WebDriverException: unknown ...
  • 错误对照

    千次阅读 2013-07-04 09:14:05
    匹配的sku参数   isv.item-update-service-error:ERROR_PUBLISH_DUPLICATE 宝贝重复发布 发生错误不要重试,提示用户重新编辑商品的信息或者下架同样的另外一个商品 isv.item-update-service-
  • 常用正则表达式匹配Antconc英文句式搭配

    千次阅读 多人点赞 2020-03-27 16:31:57
    文章目录一、正则常用特殊字符二、正则常用元字符三、英文常用词性对照表整理四、使用案例附录-完整词性表 一、正则常用特殊字符 字符 描述 ^ 匹配输入字符串的开始位置。 $ 匹配输入字符串的结束位置。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 507
精华内容 202
关键字:

对照匹配