2011-12-07 1 views
2

Perlプログラミングの新機能です。 ファイルのデータを読み込み、列1と列2のレコードをソートして、繰り返しレコードを削除し、ソートしたレコードを別のファイルに保存します。私のデータperlを使用して1列目と2列目のユーザーデータを並べ替える方法

は、次のとおり

第一列と2列目には、私がUSER1名前の最初のソートレコードをしたいと私は削除する、名前USER2とも並べ替えの時に、この例ではタブ

user1 name  user2 name 

    abc    xyz 
    adc    xyz 
    abc    xyz 
    pqr    tyu 
    xyz    abc 
    tyu    pqr 
    abc    pqr 

によって分離され、繰り返し記録する。

出力は、私たちはこのPerlを実装する方法教えてください従っ

user1 name  user2 name 
    abc    pqr 
    abc    xyz 
    adc    xyz 
    pqr    tyu 
    tyu    pqr 
    xyz    abc 

とすべきですか?

答えて

1

すべてはデータの保存方法によって異なります。私はあなたがクラスに入っているのであなたの情報をどのように保存する予定か分かりませんし、参照について知っているかもしれません。たとえば、あなたが参照を知っていない場合、あなたはこのような何かを行う可能性があります:

my @array; 
foreach my $value (<INPUT>) { 
    chomp $value; 
    my ($user1, $user2) = split (" ", $value); 
    push (@array, "$user1:$user2"); 
} 

これは、1つの文字列として両方の値を格納します。これは、リファレンスを知らない場合には、かなり一般的です。

あなたが言及について知っている場合、あなたはおそらくこれを行うだろう:

my @array; 
foreach my $value (<INPUT>) { 
    chomp $value; 
    my @line = split (" ", $value); 
    push (@array, \@line); 
} 

を私はあなたを伝えることができることはsortサブルーチンはあなたが値を比較し、ソートする関数を作成することを可能にするということです。 sortで独自の関数を使用すると、ソートする値を表す2つの値$a$bが得られます。これらを操作すると、$ aが$bより大きい場合は、$a$bまたは1より小さい場合は-1を返し、等しい場合はゼロを返します。 Perlは2つの演算子<=>cmpを用意しています。

参照をまだ学習していないので、値を$user1:$user2として保存しているとします。ソートルーチンはこのように見えるかもしれません。

sub sort { 
    my ($a_col1, $a_col2) = split (/:/, $a); 
    my ($b_col1, $b_col2) = split (/:/, $b); 

    # Now we compare $a to $b. First, we can compare the 
    # User 1 column: 

    if ($a_col1 lt $b_col1) { 
     return -1; #$a < $b 
    } 
    elsif ($a_col1 gt $b_col1) { 
     return 1;  #$a > $b 
    } 

    # If we're down here, it's because column 1 matches 
    # for both $a and $b. We'll have to compare column #2 
    # to see which one is bigger. 

    if ($a_col2 lt $b_col2) { 
     return -1; #$a < $b 
    } 
    elsif ($a_col2 gt $b_col2) { 
     return 1; #$a > $b 
    } 

    #We're down here because both column #1 and column #2 match for both 
    #$a and $b. They must be equal 

    return 0; 
} 

さて、私の並べ替えは、次のようなものになります。

my @new_array = sort(\&sort, @array); 

を注意:これは私が個人的にそれを行うだろう方法ではありません。私はおそらくcmpオペレータの組み込みを使用し、いくつかのショートカットを取るだろう。しかし、私はこれを分割して分かりたいと思っています。

ところで、教師が第1列の前に第2列をソートする必要があると判断した場合は、小文字と大なり記号を前後に変更するだけで簡単にsortサブルーチンを変更できます。

#! /usr/bin/env perl 

use strict; 
use warnings; 

#Putting my data in `@array` 

my @array; 
foreach my $entry (<DATA>) { 
    chomp $entry; 
    my ($user1, $user2) = split " ", $entry; 
    push @array, "$user1:$user2"; 
} 

# Sorting my data 

my @new_array = sort \&sort, @array; 

#Now printing out my data nice and sorted... 

foreach my $element (@new_array) { 
    my ($user1, $user2) = split (/:/, $element); 
    print "$user1\t\t$user2\n"; 
} 

# 
# END OF PROGRAM 
################################################## 

################################################## 
# Sort subroutine I'm using to sort the data 
# 
sub sort { 
    my ($a_col1, $a_col2) = split (/:/, $a); 
    my ($b_col1, $b_col2) = split (/:/, $b); 

    # Now we compare $a to $b. First, we can compare the 
    # User 1 column: 

    if ($a_col1 lt $b_col1) { 
     return -1; #$a < $b 
    } 
    elsif ($a_col1 gt $b_col1) { 
     return 1;  #$a > $b 
    } 

    # If we're down here, it's because column 1 matches 
    # for both $a and $b. We'll have to compare column #2 
    # to see which one is bigger. 

    if ($a_col2 lt $b_col2) { 
     return -1; #$a < $b 

    } 
    elsif ($a_col2 gt $b_col2) { 
     return 1; #$a > $b 
    } 

    #We're down here because both column #1 and column #2 match for both 
    #$a and $b. They must be equal 

    return 0; 
} 

__DATA__ 
david  fu 
david  bar 
albert  foofoo 
sandy  barbar 
albert  foobar 
4
#!/usr/bin/env perl 
use strict; 
use warnings; 
my @list = <DATA>; 
my $prev; 
for (sort @list) { 
    next if $prev && $_ eq $prev; 
    $prev = $_; 
    print; 
} 
__DATA__ 
    abc    xyz 
    adc    xyz 
    abc    xyz 
    pqr    tyu 
    xyz    abc 
    tyu    pqr 
    abc    pqr 
1

多分ない製品コードに値するが、ここでのアプローチです:

#!/usr/bin/perl 

use strict; 
use warnings; 

my %seen; 
print join "", 
    grep {$_ !~ /^\s+$/ && !$seen{$_}++} 
    sort {$a !~ /^ user/ <=> $b !~ /^ user/ || 
    $a cmp $b} <DATA>; 

__DATA__ 
user1 name  user2 name 

    abc    xyz 
    adc    xyz 
    abc    xyz 
    pqr    tyu 
    xyz    abc 
    tyu    pqr 
    abc    pqr 

出力:

user1 name  user2 name 
    abc    pqr 
    abc    xyz 
    adc    xyz 
    pqr    tyu 
    tyu    pqr 
    xyz    abc 

ここで最も独創的な部分が$a !~ /^ user/ <=> $b !~ /^ user/ソート条件です。 $a !~ /^ user/は、0(偽)と評価される最初の行を除くすべての行について、1(真)を評価するので、ヘッダーが最初に置かれ、末尾の行が2番目のソート条件になり、

0

それともような単純なものでした:

print sort <DATA>; 

__DATA__ 
    abc xyz 
    pqr tyu 
    xyz abc 
    adc xyz 
    tyu pqr 
    abc pqr 
    abc xyz 

しかし、あなたのデータは、このような単純な場合にのみ


ここに私のテストプログラムです。各列のデータの長さが異なる場合は、 各列は最長の項目と同じ幅でなければなりません。

__DATA__ 
    abc    |xyz  |<-- other data in record... 
    pqrwf   |tyu  |<-- other data in record... 
    xyzsder   |abc  |<-- other data in record... 
    adca    |xyzghrt |<-- other data in record... 
    tyuvdfcg   |pqr  |<-- other data in record... 
    abcvfgfaqrt  |pqrbb  |<-- other data in record... 
    abcaaaaaaaaaaa |xyz  |<-- other data in record... 

この場合、単純なソートは引き続き機能しますが、これらの列はタブではなくスペースで埋められることに注意してください。

関連する問題