動的配列は便利ですが、言語ごとの違いにはちょくちょく悩まされます。

連想配列のlengthプロパティ - 馬鹿と天才は紙一重
って使えないんですね。
var array = [];
array["a"] = "string a";
array["b"] = "string b";

console.log(array.length);
見事に0が返ってきます。意味が分かりません。

perl5

最も直感的な実装。

  • 要素数:最大の添字+1
  • 列挙:要素が空でもなされる
use 5.012;
my @fizzbuzz;
for my $i (1..30) {
    $fizzbuzz[$i] .= 'Fizz' if $i % 3 == 0;
    $fizzbuzz[$i] .= 'Buzz' if $i % 5 == 0;
}
say 0+@fizzbuzz;
say for @fizzbuzz;

ruby1.9

Perlと同様です。

fizzbuzz = []
1.upto(30).each do |i|
    fizzbuzz[i] = (fizzbuzz[i] || '') + 'Fizz' if i % 3 == 0
    fizzbuzz[i] = (fizzbuzz[i] || '') + 'Buzz' if i % 5 == 0
end
puts fizzbuzz.length;
fizzbuzz.each { |v| puts v }

php5

で、前の二つに慣れるとこれで引っかかるわけです。

  • 要素数:空でない要素の数
  • 列挙:空要素は無視する
<?php

$fizzbuzz = array();
for ($i=1;  $i <= 30; $i++){
    if ($i % 3 === 0) $fizzbuzz[$i] .= 'Fizz';
    if ($i % 5 === 0) $fizzbuzz[$i] .= 'Buzz';
}
echo count($fizzbuzz), "\n";
foreach ($fizzbuzz as $value){
    echo $value, "\n";
}

?>

要するにPHPのarrayとは配列のふりをした連想配列であり、添字は先頭からのオフセットではなく、連想配列のキーである、と。

JavaScript

実はJavaScriptの配列もそうなのですが、要素数の扱いが異なります。

  • 要素数:最大の添字+1
  • 列挙:空要素は無視する
var fizzbuzz = [];
for (var i = 1; i <= 30; i++) {
    if (i % 3 == 0) fizzbuzz[i] = (fizzbuzz[i] || '') + 'Fizz';
    if (i % 5 == 0) fizzbuzz[i] = (fizzbuzz[i] || '') + 'Buzz';
}
console.log(fizzbuzz.length);
fizzbuzz.forEach(function(v){ console.log(v) });

python3

Pythonのリストは以下がエラーとなるという意味で、「動的配列」とは似て異なるものです。

universe = []
universe[42] = 'the answer'

別の言い方をすると、Pythonのリストは空要素を許さないわけです。

これは粗配列(sparse array)を作りにくいという意味では欠点ですが、要素の初期化を強制するという点では利点とも言えます。

fizzbuzz = ['']*31
for i in range(1,31):
    if i % 3 == 0:
        fizzbuzz[i] += 'Fizz'
    if i % 5 == 0:
        fizzbuzz[i] += 'Buzz'
print(len(fizzbuzz))
for v in fizzbuzz:
    print(v)

粗配列は連想配列(辞書)を使えばいいのですし。

fizzbuzz = {}
for i in range(1,31):
    if i % 3 == 0:
        if i in fizzbuzz:
            fizzbuzz[i] += 'Fizz'
        else:
            fizzbuzz[i]  = 'Fizz'
    if i % 5 == 0:
        if i in fizzbuzz:
            fizzbuzz[i] += 'Buzz'
        else:
            fizzbuzz[i]  = 'Buzz'
print(len(fizzbuzz))
for k,v in fizzbuzz.items():
    print(v)

まとめ

  • 連想配列は配列を兼ねることもできるし、そういう実装の言語もある
    • その場合、空要素の扱いに注意を要する
  • リストは配列に似ているがそうだとは限らない
    • その場合、粗配列には明示的に連想配列を使うこと

Dan the Man with too Many Arrays to Fill