A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
関数型プログラムになれてれば
読めるコードですけど,Perl風味が混じってるので
ちょっとしんどいですね.
リファレンスを知ってるかどうかが重要です.
{map{$_,1}@array2 }-> {$_}
ここが何をしてるのかわかれば,大体OKかな
map{$_,1}@array2
の部分では,@array2の要素を一個じつ$_1にいれて
1とペアにしています.たとえば,@array2=(a,b,c,d)だったら
aを$_にして,a,1 をつくって
bを$_にして,b,1をつくって・・・とやって
(a,1,b1,c,1,d,1)
というリストを作ります.これがmapの機能
これを { } で囲んで
{ (a,1,b1,c,1,d,1) }
というのを作るんだけども,これは
{ a,1,b1,c,1,d,1 }
と同じで,無名のハッシュ(ハッシュのリファレンス)を
作る.つまり
{a=>1, b=>1, c=>1, d=>1}
と同じ.
リストをそのままハッシュに変換できるということと,それを
無名ハッシュのコンストラクタで処理してるところが
かなりPerl風味です.
このハッシュリファレンスに対して
>{map{$_,1}@array2 }-> {$_}
とするんだけども,後ろの$_はgrepが渡してくる
@array1の各要素ですので
@array1=(a,b,d,x)だとすると
a に対しては 1
b に対しては 1
d に対しては 1
x に対しては undef
となります.
これを ! で否定するのだから
a に対しては false
b に対しては false
d に対しては false
x に対しては true
がでてきて
grepではtrueになるものだけがでてくるので
結果として
@deff=(x)となります.
例では,
@array1=(a,b,d,x)
@array2=(a,b,c,d)
なので,これは,
@array1の中にあって
@array2の中にはない要素を引っ張り出す
というのが正しい言い方であって
一概に「配列を比較する」といいきれるかは微妙です.
そもそも「配列を比較する」ということ自体が
どういう意味かが明確ではないということにも注意が必要です.
No.2
- 回答日時:
> "@deff = grep { !{map{$_,1}@array2 }-> {$_}}@array1;"で比較ができると書かれていました。
もちろんこういうやり方もアリなのですが、初心者の場合後から見た場合に意味が分かる事が重要だと思うので(理解するまでに結構時間がかかった...)次のようなサブルーチンを書いてみました。
サブルーチンにするとどうしても渡された値が正しいかチェックしなければならないため冗長なコードになりますが...
sub eq_array (&;$$) {
my ($pred, $array1, $array2);
if (ref $_[0] eq 'CODE') {
# もしも最初が{ ... }だった場合
($pred, $array1, $array2) = @_;
} else {
# 普通に配列のリファレンス二つが渡された場合
($array1, $array2) = @_;
}
# 配列の数が同じかチェック
if (@$array1 != @$array2) {
return 0;
}
for (my $i = 0; $i < @$array2; $i++) {
if (defined $pred) {
# 最初が{ ... }だった場合
local ($a, $b) = ($array1->[$i], $array2->[$i]);
if (! $pred->()) {
return 0;
}
} else {
# デフォルトは文字で比較 (sortと同じ)
if ($array1->[$i] ne $array2->[$i]) {
return 0;
}
}
}
# 最後まで一緒だったら真
return 1;
}
このサブルーチンはsort演算子に動きを合わせてあります。
使い方は文字で比較する場合、
eq_array \@array1, \@array2
と配列のリファレンスを渡してください。
それぞれの要素について
$a eq $b
で比較されます。
数値で比較する場合はsort演算子のように
eq_array { $a == $b } \@array1, \@array2
としてください。
それぞれの要素について
$a == $b
のように比較されます。
以下このサブルーチンのテストをした時のコードです。
my @array1 = my @array2 = 1 .. 100;
printf "equal?:%d\n", eq_array_str(\@array1, \@array2);
printf "equal?:%d\n", eq_array_num(\@array1, \@array2);
printf "equal?:%d\n", eq_array \@array1, \@array2;
printf "equal?:%d\n", eq_array { $a == $b } \@array1, \@array2;
@array1 = "a" .. "z";
@array2 = reverse @array1;
# use warningsをしていると
# 数値に変換できない文字列を
# ==で比較すると警告を出してくるので
# ここでは数値では比較しない
printf "equal?:%d\n", eq_array_str(\@array1, \@array2);
# printf "equal?:%d\n", eq_array_num(\@array1, \@array2);
printf "equal?:%d\n", eq_array \@array1, \@array2;
# printf "equal?:%d\n", eq_array { $a == $b } \@array1, \@array2;
表示結果:
equal?:1
equal?:1
equal?:1
equal?:1
equal?:0
equal?:0
No.1
- 回答日時:
#!/usr/bin/perl
use warnings;
use strict;
my @array1 = qw(111 222 333 444 555);
my @array2 = qw(222 444);
my @diff;
# オリジナル
@diff = ();
@diff = grep {
!{ map { $_, 1 } @array2 }->{$_}
} @array1;
print "---\n";
print $_, " " foreach @diff;
print "\n";
# map { $_, 1 } @array2 とほぼ同じ働き
my %hash = ( 222, 1, 444, 1);
# 上記は%hash = ( 222 => 1, 444 => 1); と同じ
@diff = ();
@diff = grep { !$hash{$_} } @array1;
print "\n---\n";
print $_, " " foreach @diff;
print "\n";
# @diff = grep { !$hash{$_} } @array1;とやりたいことは同じ
@diff = ();
@diff = grep { !(defined $hash{$_}) } @array1;
print "\n---\n";
print $_, " " foreach @diff;
print "\n";
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) 配列操作について 5 2023/04/18 07:27
- BTOパソコン PCの選び方 6 2022/09/11 00:16
- Perl perlで2次元配列をサブルーチンに値渡しで渡す 5 2022/12/17 18:49
- Access(アクセス) Accessテキストボックス内に2つのフィールドの値を比較して大きい方の値を表示させる方法 1 2022/09/09 10:50
- 声優 声真似が全く上達しません。 練習方法を調べても、「ひたすら自分の声と聴き比べる」としか書かれていませ 5 2023/04/18 23:33
- Visual Basic(VBA) 比較して等しくなかったらセルを赤くする 4 2022/07/19 20:11
- Google Maps 同じ住所か比較 3 2023/04/29 19:16
- 日本語 「名詞+的」で「形容動詞」? 9 2023/01/26 18:30
- Perl perlでリテラル値はメモリにどのように格納されているか? 1 2023/01/15 20:45
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
データベースから取得したデー...
-
index関数で複数個抜き出す
-
perlで2つの配列を比較する方...
-
VBのReturnの使い方
-
画面を強制的に再描画させる方法
-
範囲指定したセルを1つずつ飛...
-
VBAで3秒だけ時間を止めたい
-
VBAでの一時停止と再開の方法
-
DoEventsが必要な理由について
-
vbscriptでIE自動入力(途中で...
-
DOSコマンドのループ内のTIMEコ...
-
Escキーを押すと、中断する時と...
-
流れ図(フローチャート)が分か...
-
ハッシュマーク以降のアドレス取得
-
再帰関数のインライン展開
-
Excel vba でコンボボックスの...
-
リストボックスに縦スクロール...
-
UWSCに制限時間を付けたいです
-
vb.netです。2次元配列の要素を...
-
forループは何故、forなのですか?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
データベースから取得したデー...
-
perlで2つの配列を比較する方...
-
perlでファイルの拡張子を除い...
-
python質問
-
QNo.3258883データベースから取...
-
組み合わせを作るアルゴリズム
-
非共通要素を抜き出す
-
アルファベットn文字の組み合わ...
-
grep関数を用いた複数行からの抽出
-
複数の配列の要素を繰り返し処...
-
桁数指定と四捨五入
-
ハッシュのハッシュの値代入で...
-
サブルーチンへ渡した配列のリ...
-
index関数で複数個抜き出す
-
二次元配列のつかいかた。
-
正規表現 perl 連続ヒットの...
-
配列に入った変数を二度使いたい
-
プログラミングについて。 1つ...
-
画面を強制的に再描画させる方法
-
VBのReturnの使い方
おすすめ情報