我需要列出文件中的唯一数字位置,然后在每个位置后枚举唯一的indel。
如果有多个不同的indel,那么我希望每个position / indel都列在不同的行上。
我认为List::MoreUtils:uniq
是最好的解决方案,但我没有运气。是否有无模块方法?
如果我的解释没有意义,请告诉我。
FILE1数据:
7065_8#10 99269 -t
7065_8#10 126477 -c
7065_8#10 413711 +T
7065_8#10 586681 -a
7065_8#10 820739 +T
7065_8#10 927102 +T
7065_8#10 942973 +T
7065_8#10 1075448 +G
7065_8#11 99269 -t
7065_8#11 126477 -t
7065_8#11 413711 +T
7065_8#11 470211 +G
7065_8#10 927102 -a
7065_8#10 942973 +T
中级结果:
99269 ( -t -t )
126477 ( -c -t )
413711 ( +T +T )
586681 ( -a )
820739 ( +T )
927102 ( +T -a )
942973 ( +T +T )
1075448 ( +G )
470211 ( +G )
最终输出:
99269 ( -t )
126477 ( -c )
126477 ( -t )
413711 ( +T )
586681 ( -a )
820739 ( +T )
927102 ( +T )
927102 ( -a )
942973 ( +T )
1075448 ( +G )
470211 ( +G )
这是我的初始(不成功)代码:
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
use 5.010;
my $outputfile = "/Users/edwardtickle/Documents/positionarray.txt";
open FILE1, "/Users/edwardtickle/Documents/CC22indelscc.txt";
open (OUTPUTFILE, ">$outputfile");
use List::MoreUtils qw(uniq);
my @bases = ();
my @words = ();
while (<FILE1>) {
if (/^\S+\s+(\d+)\s+(\S+)/) {
push @words, $1;
}
}
my @unique_words = uniq @words;
print OUTPUTFILE "@unique_words\n";
close FILE1;
close OUTPUTFILE;
目前这给我一个由空格分隔的一行上的唯一位置列表,我不知道如何每行打印一个。
答案 0 :(得分:2)
好的,我会列出错误列表,而不是将它们作为评论发布,因为它们开始加载。
\@unique_words "@bases";
是语法错误。你需要在它们之间加一个逗号。my @words = (); my @uniq_words = uniq @words;
除了空列表外无法生成任何内容。使用my
时,在该范围(块)中创建一个新变量。my @words = qw($1);
。这是错误的,因为:
=
代替push,qw($1)
不会插入变量,因此它只返回文字$1
。你根本不需要qw()
,而应该把价值推到另一条线上。这是你做的事情:
my ($junk, $num, $indel) = split
。 <>
,而不是显式打开输入和输出文件。 while (<>)
和perl script.pl input.txt > output.txt
。$data{$num}{$indel}++
。如果您需要保留订单,请将唯一编号存储在数组中。print "$num ( " . join(" ", keys %{$data{$num}}) . ")\n";
修改强>
阅读评论后,很明显订单无关紧要,并且&#34; indels&#34;应该分开排列。这使我们可以简单地打印文件中显示的值(保留原始顺序),并保留同时打印的副本。
use strict;
use warnings;
my %data;
while (<>) {
my ($junk, $num, $indel) = split;
unless (exists $data{$num}{$indel}) {
print "$num ( $indel )\n";
}
$data{$num}{$indel}++;
}
<强>用法:强>
perl program.pl input.txt > output.txt
事实上,作为纯粹的学术练习,这可以进一步减少。通过(ab)使用postfix incrementmentation ++
第一次在未初始化的值上使用时返回false值的事实,我们可以结合检查和增量:
my %data;
while (<DATA>) {
my ($junk, $num, $indel) = split;
unless ($data{$num}{$indel}++) { # both check and incrementation
print "$num ( $indel )\n";
}
}
请注意,这只是为了好玩,不建议用于生产代码,因为它相当模糊。
答案 1 :(得分:2)
我认为这个程序按照你的要求行事,但你的问题并不清楚。它构建了哈希散列,无需单独的uniq
调用。
我不清楚数字位置或 indels 是什么,特别是因为你的Perl代码中没有出现任何术语,但我已经做了最好的猜测。< / p>
我能说的是位置/插入对的顺序是否在一个位置有多个indel的情况下很重要。此代码按照它们在哈希中出现的顺序打印它们,这实际上是随机的。如果您需要不同的顺序,例如按字母顺序排列,或者与文件中出现的顺序相同,那么您必须这样说。
我相信您很乐意改变此解决方案,使其能够读取和写入外部文件,而不是使用DATA
和STDOUT
?
use strict;
use warnings;
my %data;
while (<DATA>) {
my ($base, $word) = (split)[1,2];
++$data{$base}{$word}
}
for my $base (sort { $a <=> $b } keys %data) {
for my $word (keys %{ $data{$base} }) {
print "$base ( $word )\n";
}
}
__DATA__
7065_8#10 99269 -t
7065_8#10 126477 -c
7065_8#10 413711 +T
7065_8#10 586681 -a
7065_8#10 820739 +T
7065_8#10 927102 +T
7065_8#10 942973 +T
7065_8#10 1075448 +G
7065_8#11 99269 -t
7065_8#11 126477 -t
7065_8#11 413711 +T
7065_8#11 470211 +G
7065_8#10 927102 -a
7065_8#10 942973 +T
<强>输出强>
99269 ( -t )
126477 ( -t )
126477 ( -c )
413711 ( +T )
470211 ( +G )
586681 ( -a )
820739 ( +T )
927102 ( +T )
927102 ( -a )
942973 ( +T )
1075448 ( +G )
答案 2 :(得分:0)
使用一个哈希,它给你的唯一性默认是这样的:
my %indel_lookup = ();
while (<FILE1>) {
if (/^\S+\s+(\d+)\s+(\S+)/) {
$indel_lookup{$1}{$2} = undef;
}
}
打印出来使用两个foreach循环
foreach my $position (keys %indel_lookup) {
foreach my $indel (keys %{$indel_lookup{$position}}) {
print "$position ( $indel )\n";
}
}
除了拼写错误(因为它未经测试),它应该可以正常工作。
答案 3 :(得分:-1)
我删除了use strict
全局变量。如果您需要use strict
,只需在全局变量前添加my
即可。这是解决方案:
#!/usr/bin/perl
#use strict;
use warnings;
use autodie;
use 5.010;
my $outputfile = "out.txt";
open FILE1, "in.txt";
open (OUTPUTFILE, ">$outputfile");
use List::MoreUtils qw(uniq);
%words = ();
while (<FILE1>) {
if (/^\S+\s+(\d+)\s+(\S+)/) {
$words{$1} .= " ".$2;
}
}
close FILE1;
for $key (keys(%words)) {
open FF, ">tmp.txt";
@uniq_words = uniq split (/\s+/,$words{$key});
for $w (@uniq_words) {
if ($w !~ /^\s*$/) {
print OUTPUTFILE "$key ( $w )\n";
}
}
}
close OUTPUTFILE;