スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

カテゴリ : スポンサー広告

tjsの配列でC#のLINQが使う

使いたかったのでArrayに関数増やしてみた。
ひとつひとつは大したこと無くても数が多くて面倒だった・・・・・・。

実際にtjsで使いどころがあるかは微妙。吉里吉里でツール作るときとかはいいかも。
使いそうなのだけコピペして使ってもいいんじゃないかしら。


/// 指定された位置の要素を返すが、添え字が範囲外の場合は例外を投げる
/// @param index 要素の位置
/// @return 指定された位置の要素
Array.elementAt = function(index) {
  if (index < 0 || index >= this.count) {
    throw new Exception("配列のindexが範囲外です");
  }
  return this[index];
};

/// 配列をコピーして返す
/// @return 配列のコピー
Array.clone = function() {
  var tmp = [];
  tmp.assign(this);
  return tmp;
};

/// 配列の各要素の関数を適用する
/// @param func 各要素を受け取って処理する関数
Array.foreach = function(func) {
  for (var i = 0; i < this.count; ++i) {
    func(this[i], i);
  }
};

/// 配列から辞書配列を生成する
/// キーが重複すると例外を投げる
/// @param keySelector 各要素を受け取ってキーを返す関数
/// @param elementSelector 各要素を受け取って辞書配列の値を返す関数
/// @return keySelectorの戻り値をキー、たいおうするelementSelectorの戻り値を値とする辞書配列
Array.toDictionary = function(keySelector, elementSelector) {
  if (elementSelector === void) elementSelector = function(elm) { return elm; };
  var tmp = %[];
  for (var i = 0; i < this.count; ++i) {
    var key = keySelector(this[i], i);
    if (tmp[key] !== voidthrow new Exception("キーが重複しています。");
    tmp[key] = elementSelector(this[i]);
  }
  return tmp;
};

/// 配列から辞書配列を生成する
/// 辞書配列の要素が配列のため、キーが重なっても格納できる
/// @param keySelector 各要素を受け取ってキーを返す関数
/// @param elementSelector 各要素を受け取って辞書配列の値の配列に入れる要素を返す関数
/// @return keySelectorの戻り値をキー、対応するelementSelectorの戻り値が入った配列を値とする辞書配列
Array.toLookup = function(keySelector, elementSelector) {
  if (elementSelector === void) elementSelector = function(elm) { return elm; };
  var tmp = %[];
  for (var i = 0; i < this.count; ++i) {
    var key = keySelector(this[i], i);
    if (tmp[key] === void) tmp[key] = [];
    tmp[key].add(elementSelector(this[i]));
  }
  return tmp;
};

/// 配列の各要素に変換関数を適用する
/// @param selector 各要素を受け取って、変換後の要素を返す関数
/// @return selectorの戻り値が入った配列
Array.select = function(selector) {
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    tmp.push(selector(this[i], i));
  }
  return tmp;
};

/// 配列の各要素に変換関数を適用する
/// 要素1つが1つ以上の要素に変換される
/// @param selector 各要素を受け取って、変換後の要素の配列を返す関数
/// @return selectorの返した配列を展開して格納した配列
Array.selectMany = function(selector) {
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    tmp.push(selector(this[i], i)*);
  }
  return tmp;
};

/// 条件を満たす要素のみを抽出する
/// @param predicate 各要素を受け取って条件を満たすか返す関数
/// @return 条件を満たす要素のみを抽出した配列
Array.where = function(predicate) {
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    if (predicate(this[i], i)) {
      tmp.push(this[i]);
    }
  }
  return tmp;
};

/// 配列の全要素を条件に従ってグループ分けする
/// @param keySelector 各要素からキーを返す関数
/// @return keySelectorの戻り値がキー、対応する各要素が入った配列が値となった辞書配列
Array.groupBy = function(keySelector) {
  var tmp = %[];
  for (var i = 0; i < this.count; ++i) {
    var key = keySelector(this[i], i);
    if (tmp[key] === void) tmp[key] = [];
    tmp[key].push(this[i]);
  }
  return tmp;
};

/// 配列を条件に従って昇順に整列する
/// @param keySelector 各要素から比較に使う値を返す関数
/// @param comparer 要素を2つ受け取って、最初の値が小さければtrueとなる関数
/// @return 整列ずみの配列
Array.orderBy = function(keySelector, comparer) {
  if (comparer === void) {
    comparer = function(first, second) { return first < second; };
  }
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    var key = keySelector(this[i], i);
    var inserted = false;
    for (var j = 0; j < tmp.count; ++j) {
      if (comparer(key, tmp[j])) {
        tmp.insert(j, this[i]);
        inserted = true;
        break;
      }
    }
    if (!inserted) tmp.push(this[i]);
  }
  return tmp;
};

/// 配列を条件に従って降順に整列する
/// @param keySelector 各要素から比較に使う値を返す関数
/// @param comparer 要素を2つ受け取って、最初の値が小さければtrueとなる関数
/// @return 整列ずみの配列
Array.orderByDescending = function(keySelector, comparer) {
  if (comparer === void) {
    comparer = function(first, second) { return first > second; };
  } else {
    comparer = function { return !comparer(...); } incontextof %[ comparer:comparer ];
  }
  return orderBy(keySelector, comparer);
};

/// 自身(outer)と指定された配列(inner)を内部結合します
/// @param outer 結合する配列
/// @param outerKeySelector 配列outerの各要素を受け取ってキーを返す関数
/// @param innerKeySelector 配列innerの各要素を受け取ってキーを返す関数
/// @param resultSelector キーが一致する配列(outer)と配列(inner)の要素を受け取って結果となる要素を返す関数
/// @return resultSelectorの戻り値が入った配列
/// Array.joinは使われているのでArray.innerJoin
Array.innerJoin = function(inner, outerKeySelector, innerKeySelector, resultSelector) {
  var outerKeys = %[];
  for (var i = 0; i < this.count; ++i) {
    var key = outerKeySelector(this[i]);
    if (outerKeys[key] === void) outerKeys[key] = [];
    outerKeys[key].add(this[i]);
  }
  
  var results = [];
  for (var i = 0; i < inner.count; ++i) {
    var key = innerKeySelector(inner[i]);
    if (outerKeys[key] === voidcontinue;
    for (var j = 0; j < outerKeys[key].count; ++j) {
      results.add(resultSelector(outerKeys[key][j], inner[i]));
    }
  }
  return results;
};

/// 自身(outer)と指定された配列(inner)を左外部結合します
/// @param outer 結合する配列
/// @param outerKeySelector 配列outerの各要素を受け取ってキーを返す関数
/// @param innerKeySelector 配列innerの各要素を受け取ってキーを返す関数
/// @param resultSelector キーが一致する配列(outer)要素と配列(inner)要素の配列を受け取って結果となる要素を返す関数
Array.groupJoin = function(inner, outerKeySelector, innerKeySelector, resultSelector) {
  var innerKeys = %[];
  for (var i = 0; i < inner.count; ++i) {
    var key = innerKeySelector(inner[i]);
    if (innerKeys[key] === void) innerKeys[key] = [];
    innerKeys[key].add(inner[i]);
  }
  
  var results = [];
  for (var i = 0; i < this.count; ++i) {
    var key = outerKeySelector(this[i]);
    results.add(resultSelector(this[i], innerKeys[key] !== void ? innerKeys[key] : []));
  }
  return results;
};

/// 配列の先頭から指定された数だけ抽出する
/// @param count 取り出す数
/// @return 配列の先頭から指定された数だけ取り出した配列
Array.take = function(count) {
  if (count > this.count) count = this.count;
  var tmp = [];
  for (var i = count-1; i >= 0; --i) {
    tmp[i] = this[i];
  }
  return tmp;
};

/// 配列の先頭から指定された数だけ飛ばして、残りを抽出する
/// @param count 飛ばす数
/// @return 配列の先頭から指定された数だけ飛ばした残りの配列
Array.skip = function(count) {
  var tmp = [];
  for (var i = count; i < this.count; ++i) {
    tmp.add(this[i]);
  }
  return tmp;
};

/// 配列の先頭から条件を満たす限りの要素を抽出する
/// @param predicate 各要素を受け取って条件を満たすか返す関数
/// @return 配列の先頭から条件を満たす限りまでの配列
Array.takeWhile = function(predicate) {
  var count = 0;
  while (predicate(this[count], count) && ++count < this.count);
  return this.take(count);
};

/// 配列の先頭から条件を満たす限りの要素を飛ばし、残りを抽出する
/// @param predicate 各要素を受け取って条件を満たすか返す関数
/// @return 配列の先頭から条件を満たす限り飛ばした残りの配列
Array.skipWhile = function(predicate) {
  var count = 0;
  while (predicate(this[count], count) && ++count < this.count);
  return this.skip(count);
};

/// 配列から同一の要素を取り除く
/// @return 重複した要素を取り除いた配列
Array.distinct = function() {
  var tmp = [];
  var values = %[];
  for (var i = 0; i < this.count; ++i) {
    var value = this[i];
    if (values[value]) continue;
    tmp.add(value);
    values[value] = true;
  }
  return tmp;
};

/// 現在の配列の後ろに、指定された配列を連結する
/// @param array 連結する配列
/// @return 連結された配列
Array.concat = function(array) {
  var tmp = [];
  tmp.push(this*, array*);
  return tmp;
};

/// 配列を添え字が同じ各要素ごとにマージする
/// 配列の長さが異なる場合、短い方の長さになる
/// @param array マージする配列
/// @param resultSelector 2つの要素を受け取って、マージした要素を返す関数
/// @return resultSelectorの戻り値が入った配列
Array.zip = function(array, resultSelector) {
  var tmp = [];
  var count = this.count > array.count ? array.count : this.count;
  for (var i = count-1; i >= 0; --i) {
    tmp[i] = resultSelector(this[i], array[i]);
  }
  return tmp;
};

/// 2つの配列の和集合を生成する
/// @param array 対象となる配列
/// @return 指定された配列との和集合の配列
Array.union = function(array) {
  var tmp = [];
  var values = %[];
  for (var i = 0; i < this.count; ++i) {
    var value = this[i];
    if (values[value]) continue;
    tmp.add(value);
    values[value] = true;
  }
  for (var i = 0; i < array.count; ++i) {
    var value = array[i];
    if (values[value]) continue;
    tmp.add(value);
    values[value] = true;
  }
  return tmp;
};

/// 2つの配列から積集合を生成する
/// @param array 対象となる配列
/// @return 指定された配列との積集合の配列
Array.intersect = function(array) {
  var values = %[];
  for (var i = this.count-1; i >= 0; --i) {
    values[this[i]] = true;
  }
  var tmp = [];
  for (var i = 0; i < array.count; ++i) {
    if (!values[array[i]]) continue;
    tmp.add(array[i]);
    values[array[i]] = false;
  }
  return tmp;
};

/// 現在の配列から、指定された配列に含まれる要素と同一の要素を除いた配列を得る(差集合)
/// @param array 対象となる配列
/// @return 指定された配列の要素を取り除いた配列
Array.except = function(array) {
  var values = %[];
  for (var i = array.count-1; i >= 0; --i) {
    values[array[i]] = true;
  }
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    if (values[this[i]]) continue;
    tmp.add(this[i]);
    values[this[i]] = true;
  }
  return tmp;
};

/// 比較関数を使用して2つの配列が同一か返す
/// @param array 比較対象となる配列
/// @param comparer 要素を比較する関数
/// @return comparerが全ての呼び出しに対してtrueを返したらtrue
Array.sequenceEqual = function(array, comparer) {
  if (this.count != array.count) return false;
  for (var i = this.count-1; i >= 0; --i) {
    if (!comparer(this[i], array[i])) return false;
  }
  return true;
};

/// 最初に条件を満たす要素を得る
/// @param predicate 条件を判定する関数
/// @param value 条件を満たす要素が存在しなかったときに返す値
/// @return 最初から見ていって最初にpredicateを満たす要素
Array.first = function(predicate, value=void) {
  for (var i = 0; i < this.count; ++i) {
    if (predicate(this[i], i)) return this[i];
  }
  return value;
};

/// 最後に条件を満たす要素を得る
/// @param predicate 条件を判定する関数
/// @param value 条件を満たす要素が存在しなかったときに返す値
/// @return 最後から見ていって最初にpredicateを満たす要素
Array.last = function(predicate, value=void) {
  for (var i = this.count-1; i >= 0; --i) {
    if (predicate(this[i], i)) return this[i];
  }
  return value;
};

/// 連続した値が要素となった配列を生成
/// @param start 開始する値
/// @param count 生成する数
/// @return start + i(0...count)の配列
Array.range = function(start, count) {
  var tmp = [];
  for (var i = count-1; i >= 0; --i) {
    tmp[i] = start + i;
  }
  return tmp;
};

/// 同じ値が連続した配列を生成
/// @param element 要素
/// @param count 要素の数
/// @return elementがcount個だけ入った配列
Array.repeat = function(element, count) {
  var tmp = [];
  for (var i = count-1; i >= 0; --i) {
    tmp[i] = element;
  }
  return tmp;
};

/// 空の配列を生成
/// @return 空の配列
Array.empty = function() {
  return [];
};

/// 条件を満たす要素が存在するか調べる
/// @param predicate 条件を判定する関数
/// @return 条件を満たす要素が1つでも存在すればtrue
Array.any = function(predicate) {
  for (var i = 0; i < this.count; ++i) {
    if (predicate(this[i], i)) return true;
  }
  return false;
};

/// 全ての要素が条件を満たすか調べる
/// @param predicate 条件を判定する関数
/// @return 全ての要素が条件を満たせばtrue
Array.all = function(predicate) {
  for (var i = 0; i < this.count; ++i) {
    if (!predicate(this[i], i)) return false;
  }
  return true;
};

/// 配列に特定の要素が存在するか調べる
/// @param value 検索する要素
/// @param comparer 2つの要素を受け取って、等しいか返す関数。省略時は === で比較
/// @return 指定された要素が1つでも存在すればtrue
Array.contains = function(value, comparer) {
  if (comparer === void) {
    comparer = function(first, secound) { return first === second; };
  }
  for (var i = 0; i < this.count; ++i) {
    if (comparer(value, this[i])) return true;
  }
  return false;
};

/// 配列の全要素を数値に変換し、その和を得る
/// @return 配列の全要素の和
Array.sum = function() {
  var v = 0;
  for (var i = this.count-1; i >= 0; --i) {
    v += +this[i];
  }
  return v;
};

/// 配列の全要素から最小値を求める
/// @return 配列の要素の中で最も小さい値
Array.min = function() {
  var v = this[-1];
  for (var i = this.count-2; i >= 0; --i) {
    if (v > this[i]) v = this[i];
  }
  return v;
};

/// 配列の全要素から最大値を求める
/// @return 配列の要素の中で最も大きい値
Array.max = function() {
  var v = this[-1];
  for (var i = this.count-2; i >= 0; --i) {
    if (v < this[i]) v = this[i];
  }
  return v;
};

/// 配列の全要素から平均値を求める
/// @return 配列の全要素の平均値
Array.average = function() {
  return this.sum() / this.count;
};

/// 配列の全要素を集計する
/// @param func 要素を集計する関数
/// @return 指定された関数で集計された結果
Array.aggregate = function(func) {
  var tmp = void;
  for (var i = 0; i < this.count; ++i) {
    tmp = func(tmp, this[i]);
  }
  return tmp;
};
スポンサーサイト

タグ : 吉里吉里 TJS

カテゴリ : TJS

コメントの投稿

非公開コメント

最新記事
カテゴリ

openclose

記事一覧
Twitter
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。