Home > action script > ActionScript 2.0 で array_count_values

ActionScript 2.0 で array_count_values

[1, "hello", 1, "world", "hello"] という配列があった時に、配列内の重複する要素の個数をカウントして、「1が2個、"hello" が2個、"world" が1個あるよ」ってのが知りたくて、調べてみたところ php の array-count-values 関数が該当することが分かりました。ActionScript2.0 では同様の関数が見当たらなかったので、似たようなのを作りました。php のソースコードの見方が分からなかったので、アルゴリズムも自力なのが不安ですが一応動いているので、誰かが添削してくれるのをうっすら期待しつつ一応公開しておきます。

追記:
いろいろご教授いただきまして、コメント欄だとコードの表示が崩れるので本文エントリに追記していきますね。ありがとうございます。
頂いたコードは全て Flash のフレームにコピペするだけで動くので、試しに動かしてみて皆さんのコードのスマートさを味わってみてください!

フレームスクリプトとして記述するタイプのごく普通の関数です。


function array_count_values(arr:Array):Array{
    //並べ替えて[1,1,"hello","hello","hello","world"]にソート
    arr.sort();
    //返り値となる2次元配列を作成。2次元目の1番目の要素を入れておく
    var returnArr:Array = new Array([arr[0],1]);
    //ループ内で使う番号
    var num:Number = 0;
    for(var i:Number = 1; i<arr.length; i++){
        //前の要素と違う要素だった時、配列を作成し、2次元配列の要素として追加する
        if(arr[i]!=arr[i-1]){
            returnArr.push(new Array(arr[i],0));
            num++;
        }
        returnArr[num][1]+=1;  
    }
    trace(returnArr[0][0]+"は"+returnArr[0][1]+"個あります"); //出力例「1は2個あります」
    return returnArr;
}

//使い方
var arr:Array = [1, "hello", 1, "world""hello""hello"];
array_count_values(arr);

返り値は2次元配列です。[[1,2],["hello",3],["world",1]] みたいな感じです。

さらにここから、array_count_values 関数の第2パラメーターに Boolean 設定して true なら「個数の多いものからソート」して [["hello",3],[1,2],["world",1]] に並べ替える機能を付けたいのだけど、2次元目の要素内容をキーにして1次元目の要素を sortOn することができるのかが分からない。

パッと思いつかないので今回は力技でなんとか乗り切ることにします。。一応実装したので、バージョン2として下に追記しておきました。

修正バージョン

降順、昇順にソートできるようにしました。第2パラメーターで「不等号の文字(<, >)」で指定するというアナログな指定方法ですw。バブルソートというアルゴリズムを使ってみました。

function array_count_values(_array:Array,sort:String):Array{
    _array.sort();
    //返り値となる2次元配列を作成。2次元目の1番目の要素を入れておく
    var returnArr:Array = new Array([_array[0],1]);
    //ループ内で使う番号
    var num:Number = 0;
    for(var i:Number = 1; i<_array.length; i++){
        //前の要素と違う要素だった時、配列を作成し、2次元配列の要素として追加する
        if(_array[i]!=_array[i-1]){
            returnArr.push(new Array(_array[i],0));
            num++;
        }
        returnArr[num][1]+=1;  
    }
    if(sort){ //バブルソート
        var tmp:Array = new Array();
        for (var i:Number = 0;i < returnArr.length - 1;i++) {
            for (var j:Number = 0;j < returnArr.length - 1;j++) {
                if(sort=="<"){ //昇順
                    if (returnArr[j + 1][1] < returnArr[j][1]) {
                        tmp = returnArr[j];
                        returnArr[j] = returnArr[j + 1];
                        returnArr[j + 1] = tmp;
                    }
                }else//降順
                    if (returnArr[j + 1][1] > returnArr[j][1]) {
                        tmp = returnArr[j];
                        returnArr[j] = returnArr[j + 1];
                        returnArr[j + 1] = tmp;
                    }
                }
            }
        }
    }
    return returnArr;
}

//使い方
var arr:Array = ["hello""world""hello""hello","oops","world","hello""world""world","hoge","hoge"];
trace(array_count_values(arr,"<")) //出力例:昇順(左が小さい順に並ぶ)
trace(array_count_values(arr,">")) //出力例:降順(右が小さい順に並ぶ)
trace(array_count_values(arr)) //出力例:ソート無し(ただし sort() はかかっている)

disable様バージョン

戻り値を連想配列にしてみるのはどうでしょうか?

function array_count_values (_array:Array):Object {
	var _obj:Object = new Object ();
	for (var i:Number = 0; i < _array.length; i++){
		_obj[_array[i]] = (_obj[_array[i]] == null) ? 1 : _obj[_array[i]] + 1;
	}
	return _obj;
}
//使い方
var arr:Array = [1, "hello", 1, "world", "hello", "hello"];
var obj:Object = array_count_values (arr); //連想配列
trace(obj["world"]) // 1
trace(array_count_values (arr)["hello"]); // 3

むらけんさんバージョン

teraさんの求める形だとこうなるでしょうか。2loopしてしまいますが。。

僕なら最後のループは消して、{value:hello,cnt:2}というObjectの入った配列を返しますかね。

function array_count_values(arr:Array,is_sort:Boolean):Array {
	var sort_array:Array = new Array();
	var fix_array:Array = new Array();
	var _obj:Object = new Object();
	for (var i:Number = 0, len:Number = arr.length; i < len; i++) {
		if (_obj[arr[i]] == undefined) {
			_obj[arr[i]] = {value:arr[i],cnt:1};
			sort_array.push(_obj[arr[i]]);
		}else{
			_obj[arr[i]].cnt++;
		}
	}
	if (is_sort)sort_array.sortOn("cnt", Array.DESCENDING | Array.NUMERIC);
	for (var j:Number = 0, len:Number = sort_array.length; j < len; j++)fix_array.push([sort_array[j].value, sort_array[j].cnt]);
	return fix_array;
}

var arr:Array = [1, "hello", 1, "world", "hello", "hello"];

var returnArr:Array = array_count_values(arr,true);
trace(returnArr[0][0]+"は"+returnArr[0][1]+"個あります"); //helloは3個あります

var returnArr:Array = array_count_values(arr);
trace(returnArr[0][0]+"は"+returnArr[0][1]+"個あります"); //1は2個あります

disable様バージョン2

あまり理解していず、申し訳ありません・・・
ちょっといじってみました。
と思ったら、むらけんさんからもっ

function array_count_values (_array:Array, _sortFlg:Boolean):Array {
     var _a:Array = new Array ();
     var _obj:Object = new Object ();
     for (var i:Number = 0; i < _array.length; i++) {
             _obj[_array[i]] = (_obj[_array[i]] == null) ? 1 : _obj[_array[i]] +1;
     }
     for(var _prop:String in _obj){;
             _a.push ({name:_prop, value:_obj[_prop]});
     }
     if(_sortFlg) _a.sortOn ("value",Array.NUMERIC | Array.DESCENDING);
     return _a;
}

//使い方
var arr:Array = [1, "hello", 1, "world", "hello", "hello"];

trace(array_count_values (arr,true)[0].name); //1番多い名前
trace(array_count_values (arr,true)[0].value); //1番多い名前の数

trace(array_count_values (arr,true)[1].name); //2番目に多い名前
trace(array_count_values (arr,true)[1].value); //2番目に多い名前の数

スマートかどうかは・・・(←スマートです! by tera)

一応お知らせ

どう書く?.org」みたいになってきましたねw。コメントにソースを書いていただくのはとてもありがたいのですが、コード中の不等号「<」をエスケープしてしまって、その行の以降のコードが消えてしまいます。不等号の部分を「アンドエルティーセミコロン」にしていただけると助かるかもです。
いや〜。アルゴリズムって面白いですね〜。(僕はまだまだですが)

Comment:10

disable 2008-02-05 (火) 15:39

戻り値を連想配列にしてみるのはどうでしょうか?

function array_count_values (_array:Array):Object {

var _obj:Object = new Object ();

for (var i:Number = 0; i < _array.length; i++){

_obj[_array[i]] = (_obj[_array[i]] == null) ? 1 : _obj[_array[i]] + 1;

}

return _obj;

}

//使い方
var arr:Array = [1, "hello", 1, "world", "hello", "hello"];

var obj:Object = array_count_values (arr); //連想配列
trace(obj["world"]) // 1

trace(array_count_values (arr)["hello"]); // 3

tera 2008-02-05 (火) 16:09

>disable様
早速のコメントありがとうございます。スマートになるもんですねぇ!勉強になります。
僕はプログラミングが未熟なので、お恥ずかしながら多次元配列と連想配列との運用上の利便性の違いがまだまだイメージできないレベルなのですが、なんとか理解できるよう努めてみます。
今後ともよろしくお願いいたします。

追記:
>「1が2個、"hello" が2個、"world" が1個あるよ」ってのが知りたくて…
って僕が書いてたからですねw。それなら連想配列を使う方が便利ですね。
ちょっと今回は「多いものから順に二次元配列に格納する」というのが欲しい形なので、引き続きいじってみます。ありがとうございますー。

むらけん 2008-02-05 (火) 17:27

teraさんの求める形だとこうなるでしょうか。
2loopしてしまいますが。。

僕なら最後のループは消して、{value:hello,cnt:2}というObjectの入った配列を返しますかね。
function array_count_values(arr:Array,is_sort:Boolean):Array {
var sort_array:Array = new Array();
var fix_array:Array = new Array();
var _obj:Object = new Object();
for (var i:Number = 0, len:Number = arr.length; i < len; i++) {
if (_obj[arr[i]] == undefined) {
_obj[arr[i]] = {value:arr[i],cnt:1};
sort_array.push(_obj[arr[i]]);
}else{
_obj[arr[i]].cnt++;
}
}
if (is_sort)sort_array.sortOn("cnt", Array.DESCENDING | Array.NUMERIC);
for (var j:Number = 0, len:Number = sort_array.length; j < len; j++)fix_array.push([sort_array[j].value, sort_array[j].cnt]);
return fix_array;
}

var arr:Array = [1, "hello", 1, "world", "hello", "hello"];

var returnArr:Array = array_count_values(arr,true);
trace(returnArr[0][0]+"は"+returnArr[0][1]+"個あります"); //helloは3個あります

var returnArr:Array = array_count_values(arr);
trace(returnArr[0][0]+"は"+returnArr[0][1]+"個あります"); //1は2個あります

No Name 2008-02-05 (火) 18:09

あまり理解していず、申し訳ありません・・・
ちょっといじってみました。
と思ったら、むらけんさんからもっ

function array_count_values (_array:Array):Array {

var _a:Array = new Array ();
var _obj:Object = new Object ();

for (var i:Number = 0; i

_obj[_array[i]] = (_obj[_array[i]] == null) ? 1 : _obj[_array[i]] + 1;

}

for(var _prop:String in _obj){;

_a.push ({name:_prop, value:_obj[_prop]});
_a.sortOn ("value",Array.NUMERIC | Array.DESCENDING);

}

return _a;

}

//使い方
var arr:Array = [1, "hello", 1, "world", "hello", "hello"];

trace(array_count_values (arr)[0].name); //1番多い名前
trace(array_count_values (arr)[0].value); //1番多い名前の数

trace(array_count_values (arr)[1].name); //2番目に多い名前
trace(array_count_values (arr)[1].value); //2番目に多い名前の数

スマートかどうかは・・・

tera 2008-02-05 (火) 18:22

>むらけんさん
ご教授ありがとうございますー。
凄い!!短い!!!
密かに僕の方でもできたので喜んでいたのに、遥かにスマートな感じですね〜。
あとでじっくり調べさせてもらいます。
ありがとうございましたー。

No Name 2008-02-05 (火) 18:23

フラグの有無入れてなかったです。。。
先程の投稿は忘れていただき、こちらを。。。

不等号も直しておきました!

function array_count_values (_array:Array, _sortFlg:Boolean):Array {

var _a:Array = new Array ();
var _obj:Object = new Object ();

for (var i:Number = 0; i < _array.length; i++) {

_obj[_array[i]] = (_obj[_array[i]] == null) ? 1 : _obj[_array[i]] + 1;

}

for(var _prop:String in _obj){;

_a.push ({name:_prop, value:_obj[_prop]});
if(_sortFlg) _a.sortOn ("value",Array.NUMERIC | Array.DESCENDING);

}

return _a;

}

//使い方
var arr:Array = [1, "hello", 1, "world", "hello", "hello"];

trace(array_count_values (arr,true)[0].name); //1番多い名前
trace(array_count_values (arr,true)[0].value); //1番多い名前の数

trace(array_count_values (arr,true)[1].name); //2番目に多い名前
trace(array_count_values (arr,true)[1].value); //2番目に多い名前の数

disable 2008-02-05 (火) 18:24

間違いだらけでテンパってまいりました!
こっちですね。。。

function array_count_values (_array:Array, _sortFlg:Boolean):Array {

var _a:Array = new Array ();
var _obj:Object = new Object ();

for (var i:Number = 0; i < _array.length; i++) {

_obj[_array[i]] = (_obj[_array[i]] == null) ? 1 : _obj[_array[i]] + 1;

}

for(var _prop:String in _obj){;

_a.push ({name:_prop, value:_obj[_prop]});

}
if(_sortFlg) _a.sortOn ("value",Array.NUMERIC | Array.DESCENDING);

return _a;

}

//使い方
var arr:Array = [1, "hello", 1, "world", "hello", "hello"];

trace(array_count_values (arr,true)[0].name); //1番多い名前
trace(array_count_values (arr,true)[0].value); //1番多い名前の数

trace(array_count_values (arr,true)[1].name); //2番目に多い名前
trace(array_count_values (arr,true)[1].value); //2番目に多い名前の数

tera 2008-02-05 (火) 18:48

>disable様
何度もご丁寧にコメントいただいて本当にありがとうございますー。そしてコードが短い!
勉強させていただく箇所が山盛りです。
このエントリ書いて良かったです。
ありがとうございます。今後ともよろしくお願いいたします。

むらけん 2008-02-05 (火) 19:55

コメント欄がコードだらけに。w
なぜかソースが欠けてしまっているので、もう一度張ってみます。

function array_count_values(arr:Array,is_sort:Boolean):Array {
var sort_array:Array = new Array();
var fix_array:Array = new Array();
var _obj:Object = new Object();
for (var i:Number = 0, len:Number = arr.length; i if (_obj[arr[i]] == undefined) {
_obj[arr[i]] = {value:arr[i],cnt:1};
sort_array.push(_obj[arr[i]]);
}else
_obj[arr[i]].cnt++;
}
if (is_sort)sort_array.sortOn("cnt", Array.DESCENDING | Array.NUMERIC);
for (var j:Number = 0, len:Number = sort_array.length; j return fix_array;
}

var arr:Array = [1, "hello", 1, "world", "hello", "hello"];

var returnArr:Array = array_count_values(arr,true);
trace(returnArr[0][0]+"は"+returnArr[0][1]+"個あります"); //helloは3個あります

var returnArr:Array = array_count_values(arr);
trace(returnArr[0][0]+"は"+returnArr[0][1]+"個あります"); //1は2個あります

tera 2008-02-05 (火) 20:19

>むらけんさん
コメントらんのコードはかけちゃってますが(←こっちも直してみました)、エントリ中にペーストさせていただいた分はちゃんと表示されてるので大丈夫だと思いますが、いかがでしょうか?

おふたかたのコードとも、こちらで動かさせていただいてきちんと動いてますー!ありがとうございます。

Comment Form

コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。

Remember personal info

Trackback:0

TrackBack URL for this entry
http://www.trick7.com/blog/mt-tb.cgi/681
Listed below are links to weblogs that reference
ActionScript 2.0 で array_count_values from trick7.com blog

Home > action script > ActionScript 2.0 で array_count_values

持っている Flash & ActionScript 関連本の中から、自分的おすすめの読む順番をご紹介。各書籍のレビューは books カテゴリからご覧頂けます。
この順番でどう?(AS3.0)
  • Adobe Flash CS3 詳細! ActionScript 3.0 入門ノート (DVD付)
    Adobe Flash CS3 詳細! ActionScript 3.0 入門ノート (DVD付)

    デザイン方面からFlashデビューして、そのままAS2.0を使うようになった人が、難しいと評判のAS3デビューする時の最初の1冊として、とにかく目を通しておくと良いかと思います。プログラミング経験の少ない方でも、サンプルをじっくり読めば、ゼロからのAS3デビュー可。
  • ActionScript 3.0 アニメーション
    ActionScript 3.0 アニメーション
    洋書「Making Things Move!」の日本語訳本。ActionScript3.0で数学的アニメーションを作ることがメインテーマなのですが、前半部分でAS3.0の基礎を分かり易く解説されています。後半の重力, IK, 3D表現等のアニメーション解説も楽しい。僕はこれのAS2.0洋書版を読んでFlashの面白さに気付きました。
  • Adobe Flash CS3 詳細! ActionScript3.0入門ノート2 (CD-ROM付)
    Adobe Flash CS3 詳細! ActionScript3.0入門ノート2 (CD-ROM付)
    この次の辞典のような洋書を読む前の事前知識としてこの本の内容を理解しておくといいかも。
  • Essential ActionScript 3.0 (Essential)
    Essential ActionScript 3.0 (Essential)

    900ページ以上ある相当分厚い本。基礎からOOPまでを解説。ほぼ網羅しているので、これを抑えておけばAS3博士になれそう。
  • Actionscript 3.0 Cookbook
    Actionscript 3.0 Cookbook

    ActionScript3.0のリファレンス本。問題とその解決法が1ページぐらいで細分化されているので空いた時間にちょっとずつ読み進められる。WebでAS3のソースを見て勉強する時の字引としても使う。ただ、時期的に初期の本なので、AS3自体が仕様変更してたりするので正誤表は必読。
  • Object-Oriented Actionscript 3.0
    Object-Oriented Actionscript 3.0

    7/23に発売されたFlash&OOP本。AS2.0版は持っているのだけど、オブジェクト指向の初歩的な解説から入って、後半は僕の理解を超える難度になっていきました。今度こそ理解できるか?
この順番でどう?(AS2.0)
  • Foundation Actionscript Animation: Making Things Move (Foundation)
    Foundation Actionscript Animation: Making Things Move (Foundation)

    スクリプトでアニメーションさせる方法を学べる。プログラムの知識というよりも数学や物理の知識が必要。バネの表現や3D表現など、汎用性の高いテクニックを身に付けられ、個人の表現力をレベルアップするのに最適。参考までに、僕が調べた英単語リスト。2007年4月に、AS3対応版も発売されました。
  • ゲーム開発のための数学・物理学入門 Beginning Math and Physics for Game Programmers
    ゲーム開発のための数学・物理学入門  Beginning Math and Physics for Game Programmers

    「Making Things Move!」の世界を突き詰めたい人用のステップアップのための本。行列や物理運動、2D/3D表現。Flashの本ではなく、じっくり読むタイプの本なので、あとまわしにしてもいいかも。
  • Flash 8 Essentials
    Flash 8 Essentials

    Flash8の新機能を紹介。全10章が独立した構成で、興味のある部分から読めます。フィルタやビットマップ、ビデオの使い方とかを、基礎から順を追って理解していけるので、ゼロからスクリプティングできるようになる。僕はビットマップ関連の作業の際のリファレンスとして常用しています。
  • .fla―Idea of Flash Creation
    .fla―Idea of Flash Creation

    上の本でFlash8の基本を身に付けて、それをどう面白い表現に落とし込むかを学べます。深津さんの、試行錯誤・実験しやすいスクリプティング、クラス設計に凄さを感じました。YouTubeやFlickrのAPI、PHPとの連携記事も。
  • FLASH ActionScript 2.0入門完全ガイド+実践サンプル集 [CD-ROM付]
    FLASH ActionScript 2.0入門完全ガイド+実践サンプル集 [CD-ROM付]

    ここまでで表現力が付き、テンションが上がるので、その勢いで難解なオブジェクト指向に挑戦。プログラム経験のない人がいきなり英語のOOP本を読むのは厳しい。この本で継承とかインターフェースとかポリモーフィズムとかの用語を理解しておくといいかも。
  • オブジェクト指向でなぜつくるのか―知っておきたいプログラミング、UML、設計の基礎知識―
    オブジェクト指向でなぜつくるのか―知っておきたいプログラミング、UML、設計の基礎知識―

    Flashの本ではありませんが、OOPの概念を気軽に読めるボリュームで解説してくれます。英語と日本語のOOP用語の対応を図るためにも「Object-oriented Actionscript for Flash 8」と併読するのがおすすめ。なんとなく読んでおくだけでも結構違うのでは。
  • Object-oriented Actionscript for Flash 8
    Object-oriented Actionscript for Flash 8

    前半はOOPの利便性や基本の紹介。デザインパターンやMVCの理解。13章からグッと難しくなって大変。Flash8対応。
  • Essential Actionscript 2.0
    Essential Actionscript 2.0

    上の本よりもさらにOOPプログラマ向け。同じOOP本ということでやや重複しており、こちらはMX2004時代の本なので見送ってもいいかも。分かりやすい英語で良著。この本のAS3版が出たら間違いなく買い。

Page Top