回答:
perlfaq4で示されているように、次のようなことができます。
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @array = qw(one two three two three);
my @filtered = uniq(@array);
print "@filtered\n";
出力:
one two three
モジュールを使用したい場合は、次のuniq
関数を試してくださいList::MoreUtils
my
このスコープでは語彙なので、問題ありません。そうは言っても、おそらくより説明的な変数名を選択することができます。
$::a
と$::b
、それは切り捨てられますね。
sub uniq { my %seen; grep !$seen{$_}++, @_ }
コストをかけずに順序を維持できるため、より優れた実装です。あるいはもっと良いのは、List :: MoreUtilsからのものを使用することです。
Perlのドキュメントには、よくあるFAQのコレクションが付属しています。あなたの質問は頻繁に尋ねられます:
% perldoc -q duplicate
上記のコマンドの出力からコピーして貼り付けた答えが以下に表示されます。
/usr/local/lib/perl5/5.10.0/pods/perlfaq4.podにあります リストまたは配列から重複した要素を削除するにはどうすればよいですか? (brian d foyによる寄稿) ハッシュを使用します。「ユニーク」または「重複」という言葉を考えるとき、 「ハッシュキー」。 要素の順序を気にしない場合は、単に ハッシュを作成してからキーを抽出します。どのようにあなたは重要ではありません そのハッシュを作成します。「キー」を使用して一意の要素を取得するだけです。 私の%hash = map {$ _、1} @array; #またはハッシュスライス:@hash {@array} =(); #またはforeach:$ hash {$ _} = 1 foreach(@array); 私の@unique = keys%hash; モジュールを使用したい場合は、から「uniq」関数を試してください 「List :: MoreUtils」。リストコンテキストでは、一意の要素を返します。 リスト内の順序を保持します。スカラーコンテキストでは、 一意の要素の数。 List :: MoreUtils qw(uniq);を使用します。 my @unique = uniq(1、2、3、4、4、5、6、5、7); #1、2、3、4、5、6、7 私の$ unique = uniq(1、2、3、4、4、5、6、5、7); # 7 各要素を確認して、見た要素をスキップすることもできます 前。ハッシュを使用して追跡します。ループが初めて見たとき 要素、その要素は%Seenにキーがありません。「next」ステートメントは、 キーとその値をすぐに使用します。これは「undef」なので、ループ 「プッシュ」を続行し、そのキーの値をインクリメントします。次は ループが同じ要素を見ると、そのキーはハッシュに存在し、 そのキーの値はtrue(0または "undef"ではないため)なので、 nextはその繰り返しをスキップし、ループは次の要素に進みます。 私の@unique =(); 私の%seen =(); 私の$ elemをforeach(@array) { 次に$ seen {$ elem} ++の場合; @ unique、$ elemをプッシュします。 } 同じことを行うgrepを使用して、これをより簡単に書くことができます 事。 私の%seen =(); 私の@unique = grep {!$ seen {$ _} ++} @array;
CPANからのList :: MoreUtilsのインストール
次に、コードで:
use strict;
use warnings;
use List::MoreUtils qw(uniq);
my @dup_list = qw(1 1 1 2 3 4 4);
my @uniq_list = uniq(@dup_list);
@dup_list
内にある必要がありますuniq
呼び出し、ない@dups
これを行う通常の方法は次のとおりです。
my %unique = ();
foreach my $item (@myarray)
{
$unique{$item} ++;
}
my @myuniquearray = keys %unique;
ハッシュを使用し、アイテムをハッシュに追加する場合。また、各項目がリストに表示される回数を知るというボーナスもあります。
シンプルなPerlワンライナーで実行できます。
my @in=qw(1 3 4 6 2 4 3 2 6 3 2 3 4 4 3 2 5 5 32 3); #Sample data
my @out=keys %{{ map{$_=>1}@in}}; # Perform PFM
print join ' ', sort{$a<=>$b} @out;# Print data back out sorted and in order.
PFMブロックはこれを行います。
@inのデータはMAPに送られます。MAPは匿名ハッシュを作成します。キーはハッシュから抽出され、@ outにフィードされます
ロジック:ハッシュは一意のキーのみを持つことができるため、配列を反復処理し、配列の各要素に任意の値を割り当て、要素をそのハッシュのキーとして保持します。ハッシュのキー、その独自の配列を返します。
my @unique = keys {map {$_ => 1} @array};
コードでこの機能を複数回使用することになっている場合は、サブルーチンを作成することをお勧めします。
sub get_unique {
my %seen;
grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);
List::MoreUtils
use List::MoreUtils qw(uniq);
my @unique = uniq(@array);
以前の回答は、このタスクを達成するための可能な方法を大まかに要約しています。
しかし、私は人のための修正示唆していない気にカウント重複しますが、実行するために気を。
my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;
以前に提案されたgrep !$seen{$_}++ ...
インクリメントは$seen{$_}
否定の前に行われることに注意してください。そのため、インクリメントはすでに行われているかどうかに関係なく行われ%seen
ます。ただし、上記$record{$_}
はtrueの場合は短絡し、一度「オフ」で聞こえた内容を残し%record
ます。
また、自動活性化とハッシュキーの存在を利用するこのばかげた機能を利用することもできます。
...
grep !(exists $record{$_} || undef $record{$_}), @record;
ただし、それによって混乱が生じる可能性があります。
また、順序や重複カウントのどちらも気にしない場合は、ハッシュスライスを使用した別のハックと、先ほど述べたトリックを実行できます。
...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped
sub uniq{ my %seen; undef @seen{@_}; keys %seen; }
ニート。
これを試してください。uniq関数が正しく機能するには、ソートされたリストが必要です。
use strict;
# Helper function to remove duplicates in a list.
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @teststrings = ("one", "two", "three", "one");
my @filtered = uniq @teststrings;
print "uniq: @filtered\n";
my @sorted = sort @teststrings;
print "sort: @sorted\n";
my @sortedfiltered = uniq sort @teststrings;
print "uniq sort : @sortedfiltered\n";
一意のハッシュキーの概念を使用:
my @array = ("a","b","c","b","a","d","c","a","d");
my %hash = map { $_ => 1 } @array;
my @unique = keys %hash;
print "@unique","\n";
出力:acbd