web-dev-qa-db-ja.com

Perl配列で一意の要素を出力するにはどうすればよいですか?

Whileステートメント中に要素を配列にプッシュしています。各要素は教師の名前です。ループが終了すると、配列の教師名が重複することになります。配列内で隣り合っていない場合もあれば、そうである場合もあります。

配列への値のプッシュが終了した後、その配列内の一意の値のみを出力するにはどうすればよいですか?要素を出力するたびに配列全体を解析する必要はありません。

すべてが配列にプッシュされた後のコードを次に示します。

$faculty_len = @faculty;
$i=0;
while ($i != $faculty_len)
{
        printf $fh '"'.$faculty[$i].'"';
        $i++;
}   
25
CheeseConQueso
use List::MoreUtils qw/ uniq /;
my @unique = uniq @faculty;
foreach ( @unique ) {
    print $_, "\n";
}
42
innaM

あなたの最善の策は、uniq( innaMで説明されているように) のような(基本的に)組み込みのツールを使用することです。

Uniqを使用する機能がなく、順序を維持したい場合は、grepを使用してそれをシミュレートできます。

my %seen;
my @unique = grep { ! $seen{$_}++ } @faculty;
# printing, etc.

これにより、最初に、各キーが各エントリであるハッシュが得られます。次に、各要素を反復処理し、要素の数をカウントして、最初の要素を追加します。 (brian d foyによるコメントで更新)

33
Robert P

ハッシュにプッシュすることをお勧めします。このような:

my %faculty_hash = ();
foreach my $facs (@faculty) {
  $faculty_hash{$facs} = 1;
}
my @faculty_unique = keys(%faculty_hash);
14
user54650
@array1 = ("abc", "def", "abc", "def", "abc", "def", "abc", "def", "xyz");

@array1 = grep { ! $seen{ $_ }++ } @array1;

print "@array1\n"; 
5
prasad

この質問は、perldocの複数のソリューションで回答されています。コマンドラインでタイプするだけです:

perldoc -q duplicate
5
Bizmarck

注意:ハッシュを含む回答の一部は、配列の順序を変更します。ハッシュはどのような種類の順序も持っていないため、キーまたは値を取得すると、順序が定義されていないリストが作成されます。

これはgrep { ! $seen{$_}++ } @facultyには適用されません

4
jmmeier

これは、一意の行を表示される順に印刷するための1行のコマンドです。

Perl -ne '$seen{$_}++ || print $_' fileWithDuplicateValues
3
VJain

私はハッキングされた3ライナーを見つけました、楽しんでください

my %uniq; 
undef @uniq(@non_uniq_array); 
my @uniq_array = keys %uniq; 
2
ryansstack

それを行うための別の方法で、注文を気にしない場合にのみ便利です:

my %hash;
@hash{@faculty}=1;
my @unique=keys %hash;

新しい変数の宣言を避けたい場合は、何らかの形で文書化されたグローバル変数 %_ を使用できます

@_{@faculty}=1;
my @unique=keys %_;
2
psxls

何らかの方法で教員リストを処理する必要がある場合は、配列を結合したキーをハッシュに変換して、キーを結合し、キーをソートすることもできます。

my @deduped = sort keys %{{ map { /.*/? ($_,1):() } @faculty }};
print join("\n", @deduped)."\n";

/.*/正規表現を変更して選択または解析し、それに応じてキャプチャしてリストを処理します。($_,1):()を任意に複雑にすることで、パスごとに1つ以上の変更された一意でないキーを出力できます。

置換正規表現を使用して処理中のデータを変更する必要がある場合、たとえば名前からドットを削除する(s/\.//g)とすると、上記のパターンに従って置換すると、元の@faculty配列が変更されます。 $_エイリアス。 $_配列の匿名コピーを作成することにより、@facultyエイリアスを回避できます(いわゆる "baby cart"演算子 を参照):

my @deduped = sort keys %{{ map {/.*/? do{s/\.//g; ($_,1)}:()} @{[ @faculty ]} }};
print join("\n", @deduped)."\n";
print "Unmolested array:\n".join("\n", @faculty)."\n";

最近のバージョンのPerlでは、keysにハッシュ参照を渡すことができ、非破壊的な置換を使用できます。

my @deduped = sort keys { map { /.*/? (s/\.//gr,1):() } @faculty };

それ以外の場合は、他の場所でのgrepまたは$seen[$_]++ソリューションが望ましい場合があります。

0
derekm