2012-04-04 9 views
0

Ich möchte eine Liste von eindeutige IDs erstellen. Da einige der IDs sind Duplikate, muss ich am Ende eine Nummer hinzufügen, um sie einzigartig zu machen, etwa so:Wie generiert man ein Array mit einem Zähler in Perl?

ID = exon00001
ID = exon00002
ID = exon00003
ID = exon00004

Hier ist was ich bisher habe.

while (loop through the IDs) { 
# if $id is an exon, then increment the counter by one and add it 
# to the end of the ID 
    if ($id =~ m/exon/) { 
    my $exon_count = 0; 
    my @exon = $exon_count++; #3 
    $number = pop @exon; # removes the first element of the list 
    $id = $id.$number; 
    print $id."/n" 
    } 
    } 

Grundsätzlich möchte ich ein Array mit einem Zähler dynamisch generieren. Es soll ein Array (1, 2, 3, 4, ...) für die Gesamtzahl der Exons erstellen, dann die Elemente entfernen und zur Zeichenkette hinzufügen. Dieser Code funktioniert nicht ordnungsgemäß. Ich denke, mit Zeile 3 stimmt etwas nicht. Weißt du das? Irgendwelche Ideen? danke

+2

Mein $ exon_count ist innerhalb der Schleife und jedes Mal auf Null gesetzt. Verschieben Sie die Deklaration vor die Schleife. Dann wird es durch die Schleife inkrementieren.Außerdem würde ich einfach $ exon_count direkt verwenden, anstatt die ganze Arbeit zu tun, um es einem Array zuzuordnen und es dann in eine Nummer zu legen, oder einfach Nummer zu verwenden und es stattdessen zu erhöhen. – Glenn

+3

Ihr Code ist mit Fehlern gespickt und selbst wenn es kompilieren würde, würde es nicht tun, was Sie denken. Zum Beispiel: Das '$ exon_count' wird jedes Mal zurückgesetzt, wenn ein neues Exon gefunden wird, Sie ordnen einem Array einen einzelnen Wert (immer 0, weil ++ danach ausgewertet wird) zu,' pop' entfernt das * letzte * Element eines *. Array *, und '"/n "' wird einen Schrägstrich und "n", wenn Sie Newline möchten, müssten Sie "" \ n "'. – TLP

+0

Um hinzuzufügen, was diese Leute sagten, 'shift' entfernt das * first * Element aus der Liste,' pop' entfernt das * last * - aber es entfernt das "oberste" Element eines Stapels, aber das ist ein * Stapel *, keine * Liste *. – Axeman

Antwort

1

Ist das, was Sie brauchen? Der Zähler muss seinen Wert behalten, so können Sie das Zurücksetzen nicht halten, wie Sie sind:

use v5.10; 

my $exon_count = 0; 
while(my $id = <DATA>) { 
    chomp $id; 
    if($id =~ m/exon/) { 
     $id = sprintf "%s.%03d", $id, $exon_count++; 
     } 
    say $id; 
    } 

__END__ 
ID=exon00001 
ID=exon00002 
ID=exon00003 
ID=exon00004 

Die Ausgabe sieht so aus:

ID=exon00001.000 
ID=exon00002.001 
ID=exon00003.002 
ID=exon00004.003 

Wenn Sie auf 5.10 oder höher sind, können Sie verwenden state die Variable innerhalb der Schleife zu erklären, aber lassen Sie es seinen Wert behalten:

use v5.10; 

while(my $id = <DATA>) { 
    chomp $id; 
    state $exon_count = 0; 
    if($id =~ m/exon/) { 
     $id = sprintf "%s.%03d", $id, $exon_count++; 
     } 
    say $id; 
    } 

ich meine, Sie Perl neu sind, da der Code wie ein Mischmasch von nicht verwandten Dinge sieht, die wahrscheinlich somet tun viel anders als du denkst. Es gibt ein Perl-Tutorial für Biologen, "Unix and Perl". Es gibt auch meine Learning Perl Buch.

Joel fragte nach einer Zeichenfolge als zusätzliches Tag. Das ist gut; Perl lässt Sie increment a string, aber nur in den Bereichen a-z und A-Z. Wir können Zahlen und Buchstaben mischen einen numerischen Tag, indem die wir in der Basis präsentieren 36:

use v5.10; 

use Math::Base36 'encode_base36'; 

while(my $id = <DATA>) { 
    chomp $id; 
    state $exon_count = 30; 
    if($id =~ m/exon/) { 
     $id = sprintf "%s.%-5s", $id, encode_base36($exon_count++); 
     } 
    say $id; 
    } 

Jetzt haben Sie Tags wie folgt aus:

ID=exon00003.1Q 
ID=exon00004.1R 
ID=exon00001.1S 
ID=exon00002.1T 
ID=exon00003.1U 
ID=exon00004.1V 
+0

+1 für 'state', einer meiner Lieblings-Perlismen –

+0

irgendwelche Gedanken über die Verwendung der magischen' $ string ++ '? Alles, was man braucht, ist eine eindeutige Kennung. Nicht wirklich benötigt, aber ein bisschen Spaß. –

+0

@JoelBerger Sie können dazu auch den Bereichsoperator verwenden, z. 'für ('exon1' .. 'exon9') {print}'. Ich würde es nicht für neue Benutzer empfehlen, da es auch Buchstaben, z. "Exon9" wird "Exoo0", nicht "Exon10", wie man meinen könnte. – TLP

1

Wie in meinem Kommentar erwähnt, kompiliert Ihr Code nicht und funktioniert nicht. Beginnen Sie mit dem Zählen der Duplikate und drucken Sie dann die korrekte Anzahl der Duplikate basierend auf den gefundenen IDs. Mit printf können Sie Ihre Nummer formatieren.

my %seen; 
my @ids = (bunch of ids); 

map $seen{$_}++, @ids; # count the duplicates 

for my $id (keys %seen) { 
    for my $num (1 .. $seen{$id}) { 
     printf "%s%05d\n", $id, $num; 
    } 
} 
0

Sie möchten eine Liste von eindeutigen IDs für diese erzeugen, Exons (um in eine GFF-Datei auszugeben?).

Sie müssen sicher sein, den Zähler außerhalb der Schleife zu initialisieren. Ich bin mir nicht sicher, was Sie mit dem Array erreichen wollten. Das unten stehende Programm generiert jedoch eindeutige Exon-IDs gemäß dem von Ihnen geposteten Format (exon00001 usw.).

my $exon_count=0; 

while(my $id=<SOMEINPUT>){ 
     if($id=~m/exon/){ 
      $exon_count++; 
     my $num='0' x (5 - length $exon_count) . $exon_count; 
      print "$id$num\n"; 
     } 
} 
+2

Das ist eine Menge Arbeit, um eine Nummer zu puffern. 'sprintf' macht das für dich. :) –

Verwandte Themen