harry’s memorandum

おれおれメモ

単語を数える例のやつ

wordcountの例題は map/reduce でよくでてくるよね。

ruby

rubyは便利。

array = %w(foo bar hoge foo foo bar fuga hoge)

h = Hash.new(0)
array.each {|e| h[e]+=1}
p h
 #=> {"fuga"=>1, "foo"=>3, "hoge"=>2, "bar"=>2}

perl

perlも便利。初期化しなくてもいいのかしら。

use Data::Dumper;

my @array = qw(foo bar hoge foo foo bar fuga hoge);
my %h = {};

foreach my $e (@array) {
  $h{$e}++;
}

print Dumper(\%h);

 #=>
  #$VAR1 = {
  #          'bar' => 2,
  #          'fuga' => 1,
  #          'foo' => 3,
  #          'hoge' => 2,
  #          'HASH(0x12af940)' => undef
  #        };

bash4

bash の version 4 からは連想配列が使える。知らない間に機能アップしている。

array=(foo bar hoge foo foo bar fuga hoge)
declare -A h # 連想配列hを宣言

for e in ${array[@]}; do
  h[$e]=$(( h[$e] + 1 ))
done

# ${h[*]}はvalues, ${!h[*]}はkeys
for e in ${!h[*]}; do
  echo "$e => ${h[$e]}"
done

 #=>
  #fuga => 1
  #bar => 2
  #foo => 3
  #hoge => 2

bash3

CentOS5/RHEL5だとbash version 3 だから連想配列は使えない。どうしようかと思ったけど意外とシンプルにかけました。連想配列が使えるawkで書けばいいというオチもありますね。

vardir=/dev/shm/var.$$
array=(foo bar hoge foo foo bar fuga hoge)

[ ! -d $vardir ] && mkdir -p $vardir
for e in ${array[@]}; do
  echo -n 1 >> $vardir/$e
done

cd $vardir
ls -l * | awk '{ print $5, "=>", $NF}'
\rm -fr $vardir

 #=>
  #bar => 2
  #foo => 3
  #fuga => 1
  #hoge => 2

awk

awkはこんな感じかな。間違っていたらごめんなさい。

array=(foo bar hoge foo foo bar fuga hoge)

echo ${array[*]} |awk \
'{
  for(i=1;NF>=i;i++)
    h[$i]++i
}
END {
  for(k in h)
    print k, "=>" h[k]
}'

#=>
 #fuga =>1
 #hoge =>2
 #bar =>2
 #foo =>3