Perl的哈希知识点

Posted 生信星球

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Perl的哈希知识点相关的知识,希望对你有一定的参考价值。

Perl的哈希知识点今天是生信星球陪你的第73天


   你想找辆共享单车,发现满街都是别家车,没有一辆你能骑。

   你想学点生信,搜了“初学者教程”,满眼尽是高大上,没有一句能看懂。

   终于你跨越茫茫宇宙,来到生信星球,发现了初学者的新大陆!


. Perl中的哈希

哈希数据是没有顺序的;使用键值对,键是唯一的,值可以相同;使用大括号调取键【数组是用中括号,这个区别要注意】;引用哈希变量用%【标量变量用$,数组变量用@ 】;哈希中存储的键值对形式:键=>值

定义空哈希:

%hash=();

将列表改成哈希:

例如有这么一份表格,表示字母与数字的对应:

wordA one
wordB two
wordC three
wordD four
wordE five
#!/usr/bin/perl -w
use Data::Dumper; #这个模块可打印出哈希的数据结构
%hash=();#先定义一个空的哈希,一会向其中存入内容

open IN,"<$ARGV[0]"#文件重定向输入
while (<IN>){ #一行一行读入该文件
    chomp# 每一行例如wordA one 去掉结尾的换行符
    @line=split /s+/,$_; #按照空格分隔,将两列存储在line数组中【$_是split的作用对象,也就是读入的每一行】
    $hash{$line[0]}=$line[1];#将第一列作为键,第二列作为值存储在之前的空哈希中。

close IN;

print Dumper (\%hash); #print加Dumper模块,再引用哈希

对哈希进行遍历:

  1. keys 函数

# keys函数也常常用在对哈希的遍历过程中
#keys和value函数定义键和值,保存到数组并打印
@key=keys %hash;
@value=value %hash;

print "@key ";
print "@value "
#返回的键值对还是一一对应的,但是键值对之间的顺序和原来列表不同

#如果将键用$存到标量而不是用@存到数组,那么返回的就是键的个数
#$key=keys %hash; 结果返回的就不是具体的键wordA-E,而是haxi的元素个数5
  1. 对哈希进行遍历也可以用foreach

# 实际上foreach是用来对数组进行遍历的,这里的@tmp就是用keys对哈希进行遍历再排序得到的数组
@tmp=sort keys %hash;
foreach (@tmp){
    print"$_ "
    print "$hash($_) ;"
}
  1. while循环中用each

while (($key,$value)=each %hash){
    print "$key $value ";
}

检测哈希中某个键是否存在:

if (exists %hash{wordA}) {
    print "$hash{wordA} ";
}

生信中的应用~
用哈希进行序列提取:

根据固定的id从另一个文件或者数据库提取出序列

一般处理方式是:将小的数据集存储到一个哈希中,然后再遍历大的数据集,每次判断id在哈希中是否存在,如果存在就输出,不存在继续循环

就想NCBI blast过程,就是根据id去找序列的过程。【那么如果将大的数据集存到哈希中,用小数据集遍历可以不可以实现呢?其实也可以,但是会消耗大量的资源,不值得!就想去blast,如果将大的NCBI nt数据库存到哈希,那么这个数据库有80多个G,是很慢的】

# 第一步:将gene id【第一个参数】存储到哈希中
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
if (scalar @ARGV==0){ #添加帮助信息,如果ARGV这个命令行参数个数为0,即没有输入的id文件和基因序列文件
    die "Usage: This program is used to extract sequence by a gene id from a gene list 
        perl $0 <id list> <fasta file>"
;
#die函数终止程序,并打印返回信息;$0意思是程序的名字

my hash=();
open IN,"<$ARGV[0]";
while (<IN>) {
    chomp;
    $hash{$_}=1;
}
close IN;
#print Dumper (\%hash);

# 第二步:读取基因序列文件【格式是每个id对应一条序列】
open FA,"<$ARGV[1]"# 打开fasta格式序列文件
$/=">";<FA>; #根据fasta的格式,将分隔符$/修改为>,这样每次读入的数据就是一个字段,也就是一个完整的基因序列。包括了id和序列
while (<FA>) { # 每次读入一个分隔后的基因
    chomp;
    my id=(split / /$_,2)[0]; #将id与序列分开~利用换行符进行分隔,存为一个为定义标量。最后加上的数字2,意思是将标量分成两份,也就是id行和序列行。然后就可以根据基因id,即分隔后的[0]进行判断
    if (exists $hash{$id}){ #判断第一步生成的哈希中的值在id中是否存在
        print ">$_"#因为原来gene id是带>的,但是$id中用$/=">"处理后就不带>,所以最后输出还需要加上>;另外输出的结果是$_,即id+序列
    } else {
        next#一个一个判断,如果不存在就检查下一个
    }
    print "$id "
}
close FA;

写完脚本可以用perl -c 查看脚本是否正确


初学生信,很荣幸带你迈出第一步。

我们是生信星球,一个不拽术语、通俗易懂的生信知识平台。需要帮助或提出意见请后台留言或发送邮件到Bioplanet520@outlook.com~


以上是关于Perl的哈希知识点的主要内容,如果未能解决你的问题,请参考以下文章

Perl_实用报表提取语言

Perl 引用的知识整理

请问怎么给perl里的标量,哈希,数组赋初值?

每日学习:Perl语言学习之哈希(Hashes)

如何有条件地将 C 代码片段编译到我的 Perl 模块?

如何在perl中删除哈希值中的重复值?