目次 ⇒ Javaアルゴリズムライブラリ-Artery-サンプル
#概要
ArMathには計算処理のメソッドが集められている。その中から配列に関係するものを紹介する。本稿の内容は次の通り。
・関連enum、インターフェースの説明
・集約処理-最大値、最小値、合計、平均、標準偏差
・変換処理-指定数値との加減乗除
・変換処理-指定ロジックによる変換
・変換処理-移動平均、変化率など
・二つの配列の合成-二つの配列の値の加減乗除
・二つの配列の合成-二つの配列の値の計算(ロジックは外部指定)
・ヒストグラムの作成-境界値は直接またはArValidatorで指定する
・おまけ(逆順とランダマイズ、Map・二次元Map上の数値の加減乗除)
ラッパー型配列とプリミティブ型の配列を変換することが必要だったりするが、(紹介はしないが)このようなメソッドも含まれている。一次元配列と二次元配列の変換もできる。
なおArListには、ここに示したようなメソッドが用意されているが、ArListではオブジェクトの中の特定フィールドを指定して、このような計算を行うことができる。
一次元配列と二次元配列について同様の機能があるが、サンプルは一次元配列で示している。
#関連enum、インターフェースの説明
###ArReduceTo
/** 数値列の集約方法の定義 */
public enum ArReduceTo {
/** 最大値 */
MAX,
/** 最小値 */
MIN,
/** 合計値 */
SUM,
/** 平均値 */
AVG,
/** 標準偏差 */
STD_DEV,
/** 予備-0 */
YOBI_0,
/** 予備-1 */
YOBI_1,
}
###ArCalc
/** 演算の種類の定義 */
public enum ArCalc {
/** 加算 */
ADD,
/** 減算 */
SUB,
/** 乗算 */
MUL,
/** 除算 */
DIV,
/** 代入 */
SET,
/** 逆減算 */
ISUB,
/** 逆除算 */
IDIV,
/** 交換 */
SWAP,
}
###ArConvertTo
/** 数値列の変換方法の定義 */
public enum ArConvertTo {
/** 移動平均 */
MOVING_AVG,
/** 変動率 */
CHANGE_RATE,
/** 変動幅 */
CHANGE_WIDTH,
/** パーセント */
PERCENT,
/** 累積値 */
ACCUMULATION,
/** ヒストグラム */
HISTOGRAM,
/** 期間集計(四半期⇒年間などに使用) */
PERIOD_SUM,
/** 予備-0 */
YOBI_0,
/** 予備-1 */
YOBI_1,
}
###ArTableRC
/** ROW,COLUMNの区別の定義 */
public enum ArTableRC {
/** ROW */
ROW,
/** COLUMN */
COLUMN;
}
###ArCreator
/** 指定されたオブジェクトから別のオブジェクトを生成するインタフェース. */
public interface ArCreator<T0,T1> {
/** argからT1クラスのオブジェクトを生成する.実装がどのような処理をしているか分からないのでExceptionをthrowしておく. */
public T1 convert(T0 arg) throws Exception;
}
###ArCreator2d
/** 二つの値を元に別の値を生成するインターフェース */
public interface ArCreator2D<$arg0,$arg1,$value> {
/** arg0とarg1から$valueクラスのオブジェクトを生成する.実装がどのような処理をしているか分からないのでExceptionをthrowしておく. */
public $value convert($arg0 arg0,$arg1 arg1) throws Exception;
}
###ArValidator
/** 指定されたオブジェクトの正当性を判定するインターフェース. */
public interface ArValidator<T> {
/**
* 指定されたオブジェクトを判定する.
* @param value 判定対象オブジェクト.
*/
public boolean check(T value);
}
#集約処理-最大値、最小値、合計、平均、標準偏差
###メソッド定義
二次元配列ではROWまたはCOLUMNを指定して集約することができる。
/** 一次元配列の集約(最大最小など) */
public static double calc(double[] doubleArray,ArReduceTo kind)
/** 二次元配列の集約(最大最小など) */
public static double[] calc(double[][] doubleArray,ArReduceTo kind,ArTableRC rowCol)
###サンプルプログラム
package jp.avaj.lib.algo;
import jp.avaj.lib.def.ArReduceTo;
import jp.avaj.lib.test.L;
/**
数値配列の集約処理-最大値、最小値、合計、平均、標準偏差
*/
public class Q09_00 {
public static void main(String[] args) {
double[] array = new double[]{1,2,3,4,5,6,7,8,9,10};
// 念のためランダマイズ
array = ArMath.randomize(array);
L.p("array="+ArObj.toString(array));
L.p("最大値="+ArMath.calc(array,ArReduceTo.MAX));
L.p("最小値="+ArMath.calc(array,ArReduceTo.MIN));
L.p("合計="+ArMath.calc(array,ArReduceTo.SUM));
L.p("平均="+ArMath.calc(array,ArReduceTo.AVG));
L.p("標準偏差="+ArMath.calc(array,ArReduceTo.STD_DEV));
}
}
###サンプル実行結果
array=[1, 5, 10, 7, 2, 4, 6, 8, 3, 9]
最大値=10.0
最小値=1.0
合計=55.0
平均=5.5
標準偏差=2.8722813232690143
#変換処理-指定数値との加減乗除
###メソッド定義
/** 一次元配列の変換 */
public static double[] convert(double[] doubleArray,ArCalc kind,double value)
/** 二次元配列の変換 */
public static double[][] convert(double[][] doubleArray,ArCalc kind,double value)
###サンプルプログラム
package jp.avaj.lib.algo;
import jp.avaj.lib.def.ArCalc;
import jp.avaj.lib.test.L;
/**
数値配列の変換処理-指定数値との加減乗除.
本サンプルでは加算処理のみを行う.
*/
public class Q09_01 {
public static void main(String[] args) {
double[] array = ArMath.doubleArray(10,new ArGeneratorDoubleRandom(10D,20D));
L.p("array="+ArObj.toString(array));
array = ArMath.convert(array,ArCalc.ADD,3D);
L.p("array="+ArObj.toString(array));
}
}
###サンプル実行結果
array=[13.348039840199508, 14.896592857645892, 17.333929293408378, 13.588269785858508, 16.036528261560278, 13.983347639430207, 12.002249957043128, 19.93148386395162, 12.337109159822935, 14.39586704149562]
array=[16.348039840199508, 17.896592857645892, 20.333929293408378, 16.588269785858508, 19.036528261560278, 16.983347639430207, 15.002249957043128, 22.93148386395162, 15.337109159822935, 17.39586704149562]
#変換処理-指定ロジックによる変換
ロジックはArCreatorで指定するものと、ArCreator2Dで指定するものがある。前者は当該の数値を使って変換し、後者は当該の数値と配列のインデックスを使って変換する。
###メソッド定義
/** 一次元配列の変換 */
public static double[] convert(double[] doubleArray,ArCreator<Double,Double> creator) throws Exception
/** 一次元配列の変換.creatorのInteger引数には配列のインデックスが指定される. */
public static double[] convert(double[] doubleArray,ArCreator2D<Double,Integer,Double> creator) throws Exception
/** 二次元配列の変換 */
public static double[][] convert(double[][] doubleArray,ArCreator<Double,Double> creator) throws Exception
/** 二次元配列の変換 */
public static double[][] convert(double[][] doubleArray,ArCreator2D<Double,Integer,Double> creator) throws Exception
###サンプルプログラム
package jp.avaj.lib.algo;
import jp.avaj.lib.test.L;
/**
数値配列の変換処理-指定ロジックによる変換
*/
public class Q09_02 {
public static void main(String[] args) throws Exception {
// テストデータ
double[] array = ArMath.doubleArray(10,new ArGeneratorDoubleRandom(5D,10D));
L.p("array="+ArObj.toString(array));
double[] newArray;
// ArCreator<Double,Double>を利用した変換
{
// ArCreatorの定義
ArCreator<Double,Double> creator = new ArCreator<Double,Double>() {
@Override
public Double convert(Double obj) throws Exception {
return obj+2D;
}
};
newArray = ArMath.convert(array,creator);
L.p("newArray="+ArObj.toString(newArray));
}
// ArCreator2D<Double,Integer,Double>を利用した変換
{
// ArCreator2Dの定義、Integerのパラメータには配列のインデックスが渡される
ArCreator2D<Double,Integer,Double> creator = new ArCreator2D<Double,Integer,Double>() {
@Override
public Double convert(Double arg0,Integer arg1) throws Exception {
return ((arg1%2)==0) ? arg0 : -arg0;
}
};
newArray = ArMath.convert(array,creator);
L.p("newArray="+ArObj.toString(newArray));
}
}
}
###サンプル実行結果
array=[5.852138560225006, 9.75606457517308, 5.4476666795846, 8.750541556076218, 9.276962894000498, 5.419291907356978, 8.018936197987681, 9.885258841879601, 8.406859998877785, 5.572972359413988]
newArray=[7.852138560225006, 11.75606457517308, 7.4476666795846, 10.750541556076218, 11.276962894000498, 7.419291907356978, 10.018936197987681, 11.885258841879601, 10.406859998877785, 7.572972359413988]
newArray=[5.852138560225006, -9.75606457517308, 5.4476666795846, -8.750541556076218, 9.276962894000498, -5.419291907356978, 8.018936197987681, -9.885258841879601, 8.406859998877785, -5.572972359413988]
#変換処理-移動平均、変化率など
###メソッド定義
/**
* ArConvertToを利用した数値の変換.ただしkindのうちヒストグラムは指定不可.
* paramは次の場合のみ意味がある.MOVING_AVG,CHANGE_RATE,CHANGE_WIDTH,PERIOD_SUM.
* またCHANGE_RATE,CHANGE_WIDTHでparamに0を指定した場合は初期値に対する変動となる.
*/
public static double[] convert(double[] array,ArConvertTo kind,int param) throws Exception
/**
* ArConvertToを利用した数値の変換.ただしkindのうちヒストグラムは指定不可.
* paramは次の場合のみ意味がある.MOVING_AVG,CHANGE_RATE,CHANGE_WIDTH,PERIOD_SUM.
* またCHANGE_RATE,CHANGE_WIDTHでparamに0を指定した場合は初期値に対する変動となる.
*/
public static double[] convert(double[][] array,ArConvertTo kind,int param,ArTableRC rowCol,int index) throws Exception
###サンプルプログラム
package jp.avaj.lib.algo;
import jp.avaj.lib.def.ArConvertTo;
import jp.avaj.lib.test.L;
/**
数値配列の変換処理-移動平均、変化率など
本サンプルでは移動平均と合計値に対するパーセントを求める.
*/
public class Q09_03 {
public static void main(String[] args) throws Exception {
// テストデータ
double[] array = ArMath.doubleArray(10,new ArGeneratorDoubleRandom(5D,10D));
L.p("array="+ArObj.toString(array));
double[] newArray;
// 四個の移動平均
{
newArray = ArMath.convert(array,ArConvertTo.MOVING_AVG,4);
L.p("newArray="+ArObj.toString(newArray));
}
// 合計値に対するパーセント
{
newArray = ArMath.convert(array,ArConvertTo.PERCENT,0); // 最後の引数は無意味
L.p("newArray="+ArObj.toString(newArray));
}
}
}
###サンプル実行結果
array=[5.985380144134761, 7.575355662184555, 7.8352635477308015, 5.149850038794702, 9.389332364999511, 5.035633917916596, 7.484603584807374, 6.847220004442178, 8.15795801332105, 9.350653554342703]
newArray=[5.985380144134761, 6.780367903159658, 7.131999784683373, 6.6364623482112055, 7.487450403427393, 6.8525199673604025, 6.764854976629546, 7.189197468041415, 6.881353880121799, 7.960108789228326]
newArray=[8.220405604471235, 10.40410043166721, 10.761061591616974, 7.072876759979646, 12.895441648951902, 6.916010726815919, 10.27946024716367, 9.404068637932905, 11.204254727155634, 12.842319624244903]
#二つの配列の合成-二つの配列の値の加減乗除
###メソッド定義
/** 一次元配列同士の演算 */
public static double[] calc(double[] doubleArray0,double[] doubleArray1,ArCalc kind)
/** 二次元配列の行・列と一次元配列の加減乗除.元の二次元配列が書き換えられる. */
public static void calc(double[][] doubleArray0,double[] doubleArray1,int index,ArCalc kind,ArTableRC rowCol)
###サンプルプログラム
package jp.avaj.lib.algo;
import jp.avaj.lib.def.ArCalc;
import jp.avaj.lib.test.L;
/**
数値配列の変換処理-二つの配列の合成-二つの配列の値の加減乗除
本サンプルでは加算と乗算を行う
*/
public class Q09_04 {
public static void main(String[] args) {
// テストデータ
double[] array0 = ArMath.doubleArray(10,new ArGeneratorDoubleRandom(5D,10D));
L.p("array0="+ArObj.toString(array0));
double[] array1 = ArMath.doubleArray(10,new ArGeneratorDoubleRandom(5D,10D));
L.p("array1="+ArObj.toString(array1));
double[] newArray;
// 加算処理
{
newArray = ArMath.calc(array0,array1,ArCalc.ADD);
L.p("newArray="+ArObj.toString(newArray));
}
// 乗算処理
{
newArray = ArMath.calc(array0,array1,ArCalc.MUL);
L.p("newArray="+ArObj.toString(newArray));
}
}
}
###サンプル実行結果
array0=[8.786527250579027, 8.475128917235198, 6.570863590659945, 9.095151921000824, 5.810489054840153, 8.574370760082004, 9.513894390034038, 7.928853544903687, 8.364814697141732, 7.496390955771403]
array1=[9.825877092616365, 6.40624152776633, 8.091125641955209, 7.508234716238508, 9.254752954661516, 6.5836384715162835, 6.050855953787648, 5.823069794583683, 7.791340507005785, 7.748951867821722]
newArray=[18.612404343195394, 14.881370445001528, 14.661989232615154, 16.603386637239332, 15.06524200950167, 15.158009231598289, 15.564750343821686, 13.75192333948737, 16.156155204147517, 15.245342823593125]
newArray=[86.3353368351139, 54.29372282276542, 53.16568288817856, 68.28853540272175, 53.77464074831031, 56.450557205120205, 57.56720451364436, 46.170267583006414, 65.1731195834377, 58.08917269864668]
#二つの配列の合成-二つの配列の値の計算(ロジックは外部指定)
###メソッド定義
変換ロジックArCreator2Dの引数には、それぞれの配列の値が指定される。
/** 一次元配列同士の演算 */
public static double[] calc(double[] doubleArray0,double[] doubleArray1,ArCreator2D<Double,Double,Double> creator) throws Exception
/** 二次元配列の行・列と一次元配列の演算.元の二次元配列が書き換えられる.*/
public static void calc(double[][] doubleArray0,double[] doubleArray1,int index,ArCreator2D<Double,Double,Double> creator,ArTableRC rowCol) throws Exception
###サンプルプログラム
package jp.avaj.lib.algo;
import jp.avaj.lib.def.ArCalc;
import jp.avaj.lib.test.L;
/**
数値配列の変換処理-二つの配列の合成-二つの配列の値の計算(ロジックは外部指定)
*/
public class Q09_05 {
public static void main(String[] args) throws Exception {
// テストデータ
double[] array0 = ArMath.doubleArray(10,new ArGeneratorDoubleRandom(5D,10D));
L.p("array0="+ArObj.toString(array0));
double[] array1 = ArMath.doubleArray(10,new ArGeneratorDoubleRandom(5D,10D));
L.p("array1="+ArObj.toString(array1));
double[] newArray;
ArCreator2D<Double,Double,Double> creator;
// サンプル0
{
creator = new ArCreator2D<Double,Double,Double>() {
@Override
public Double convert(Double arg0,Double arg1) throws Exception {
return arg0 + arg1;
}
};
newArray = ArMath.calc(array0,array1,creator);
L.p("newArray="+ArObj.toString(newArray));
}
// サンプル1
{
creator = new ArCreator2D<Double,Double,Double>() {
@Override
public Double convert(Double arg0,Double arg1) throws Exception {
return arg0 * arg1;
}
};
newArray = ArMath.calc(array0,array1,ArCalc.MUL);
L.p("newArray="+ArObj.toString(newArray));
}
}
}
###サンプル実行結果
array0=[5.494186340089856, 7.735644497901893, 9.972069234046275, 7.934361174668532, 9.917112507755494, 5.151322997853091, 9.188756724966979, 6.353024733860859, 8.223364931681369, 5.106895727778108]
array1=[9.363650797189873, 7.332827778640875, 9.2790020579598, 5.158181941401007, 5.763411771209263, 6.158648211398885, 9.22867429510773, 9.781626836497223, 8.291547420073364, 5.795528562585907]
newArray=[14.857837137279729, 15.068472276542767, 19.251071292006074, 13.092543116069539, 15.680524278964757, 11.309971209251977, 18.41743102007471, 16.13465157035808, 16.51491235175473, 10.902424290364014]
newArray=[51.44564230329209, 56.72414885990545, 92.530850944833, 40.926878527728505, 57.15640296360463, 31.725186167065885, 84.80004299170105, 62.142917229664, 68.18442028360442, 29.597160056485965]
#ヒストグラムの作成-境界値は直接またはArValidatorで指定する
なおArListでは数値ではなく、任意のオブジェクトに対するヒストグラムを作成するメソッドが用意されている。境界値はArValidatorで指定する。
###メソッド定義
/**
* ヒストグラムを作成する.doudaryのlength-1の値が戻される.
* boundary[0],boundary[length-1]にはnullを指定できる.その場合は無限値と解釈される.
*/
public static int[] histogram(double[] array,Double[] boundary) throws Exception
/** ヒストグラムを作成する.validators.lendth-1の値が戻される. */
public static int[] histogram(double[] array,ArValidator<Double>[] validators) throws Exception
###サンプルプログラム
package jp.avaj.lib.algo;
import jp.avaj.lib.test.L;
/**
ヒストグラムの作成-境界値は直接またはArValidatorで指定する
*/
public class Q09_06 {
public static void main(String[] args) throws Exception {
// テストデータ ⇒ 1.0~10.0の配列を作成する
double[] array = ArMath.doubleArray(10,new ArGeneratorDoubleSeq(1D,1D));
// あらぬ疑いを避けるためにランダマイズする
array = ArMath.randomize(array);
L.p("array="+ArObj.toString(array));
int[] result;
// 境界値を直接指定する
{
// 両端をnullにすれば無限値となる
Double[] boundary = new Double[] {
null,4.0D,8.0D,null
};
result = ArMath.histogram(array,boundary);
L.p("result="+ArObj.toString(result));
}
// 境界値をArValidatorで指定する
{
// ArValidatorの配列の作成 ⇒ 一例なのでよろしく
Double[][] boundary = new Double[][] {
{null,4.0D},
{4.0D,8.0D},
{8.0D,null},
};
ArValidator<Double>[] validators = ArValidatorUtil.createArValidatorDoubleRangeArray(boundary);
result = ArMath.histogram(array,validators);
L.p("result="+ArObj.toString(result));
}
}
}
###サンプル実行結果
array=[6, 9, 1, 3, 5, 7, 2, 8, 10, 4]
result=[3, 4, 3]
result=[3, 4, 3]
#おまけ
###逆順とランダマイズ
/** 一次元配列の逆順 */
public static double[] reverse(double[] doubleArray)
/** 一次元配列のランダマイズ */
public static double[] randomize(double[] doubleArray)
/** 二次元配列の行・列の逆順,indexが-1の時はすべてのRowまたはColumn */
public static double[][] reverse(double[][] doubleArray,int index,ArTableRC rowCol)
/** 二次元配列の行・列のランダマイズ,indexが-1の時はすべてのRowまたはColumn */
public static double[][] randomize(double[][] doubleArray,int index,ArTableRC rowCol)
package jp.avaj.lib.algo;
import jp.avaj.lib.test.L;
/**
逆順とランダマイズ
*/
public class Q09_07 {
public static void main(String[] args) {
// テストデータ ⇒ 1.0~10.0の配列を作成する
double[] array = ArMath.doubleArray(10,new ArGeneratorDoubleSeq(1D,1D));
L.p("array="+ArObj.toString(array));
double[] newArray;
// 逆順
newArray = ArMath.reverse(array);
L.p("newArray="+ArObj.toString(newArray));
// ランダマイズ
newArray = ArMath.randomize(array);
L.p("newArray="+ArObj.toString(newArray));
}
}
array=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
newArray=[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
newArray=[8, 1, 7, 9, 10, 6, 5, 4, 2, 3]
###Map、二次元Map上の数値の加減乗除
Mapあるいは二次元Map(ArMatrix)上のInteger値を更新する。返値は更新後の値。
/**
* 値がIntegerのMapの加減乗除.指定されたキーに対応する値とvalueの演算を行う.
* 除算の場合は、切り捨てて整数化する.
* Mapにキーが存在しない場合は、加減の場合は0、乗除の場合は1を仮定する.
*/
public static <$Key> int calc(Map<$Key,Integer> map,$Key key,ArCalc op,Integer value)
/**
* 値がIntegerのArMatrixの加減乗除.指定されたキーに対応する値とvalueの演算を行う.
* 除算の場合は、切り捨てて整数化する.
* ArMatrixにキーが存在しない場合は、加減と交換の場合は0、乗除の場合は1を仮定する.
*/
public static <$Key0, $Key1> int calc(ArMatrix<$Key0,$Key1,Integer> mat,$Key0 key0,$Key1 key1,ArCalc op,Integer value)
package jp.avaj.lib.algo;
import java.util.HashMap;
import java.util.Map;
import jp.avaj.lib.def.ArCalc;
import jp.avaj.lib.test.L;
/**
Map、二次元Map上の数値の加減乗除
*/
public class Q09_08 {
public static void main(String[] args) {
int result;
L.p("Mapの場合");
{
// 初期値を適当に入れておく
Map<String,Integer> map = new HashMap<String,Integer>();
map.put("a",3);
map.put("b",4);
map.put("c",5);
// 加減算では存在しないキーでは0が設定されていると仮定、徐除算では1.
result = ArMath.calc(map,"d",ArCalc.ADD,2);
L.p("result="+result);
result = ArMath.calc(map,"d",ArCalc.MUL,3);
L.p("result="+result);
}
L.p("二次元Map(ArMatrix)の場合");
{
// 初期値を適当に入れておく
ArMatrix<String,String,Integer> mat = new ArMatrix<String,String,Integer>();
mat.put("a0","b0",7);
mat.put("a1","b1",3);
mat.put("a0","b1",5);
mat.put("a1","b0",6);
result = ArMath.calc(mat,"a","b",ArCalc.ADD,2);
L.p("result="+result);
result = ArMath.calc(mat,"a","b",ArCalc.MUL,3);
L.p("result="+result);
}
}
}
Mapの場合
result=2
result=6
二次元Map(ArMatrix)の場合
result=2
result=6
==== end.