MapとReduce

Pythonでよく使ってるMapとReduceをDelphi2009で実装してみた。
この辺の人がすでにうまいことやってるっぽいけども・・・。

map.pas

unit map;

interface

uses
  Generics.Collections;

type
  TFunc<T> = reference to function (Value: T): T;
  TFunc2<T> = reference to function (Base, Value: T): T;

  TFuncTools<T> = class
  public
    class function Map(Func: TFunc<T>; const List: TList<T>): TList<T>;
    class function Reduce(Func: TFunc2<T>; const List: TList<T>): T;
  end;


implementation

class function TFuncTools<T>.Map(Func: TFunc<T>; const List: TList<T>): TList<T>;
var
  Value: T;
begin
  Result := TList<T>.Create;
  for Value in List do
    Result.Add(Func(Value));
end;

class function TFuncTools<T>.Reduce(Func: TFunc2<T>; const List: TList<T>): T;
var
  I: Integer;
begin
  Result := List[0];
  for I := 1 to List.Count - 1 do
    Result := Func(Result, List[I]);
end;

end.

sample.dpr

1〜5の数値のリストをMapで二乗する。Reduceで合計する。

program sample;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Generics.Collections,
  map in 'map.pas';

var
  list, list2: TList<Integer>;
  i, j: Integer;

begin
  list := TList<Integer>.Create;
  try
    for i := 1 to 5 do
      list.Add(i);

    list2 := TFuncTools<Integer>.Map(
      function (Value: Integer): Integer
      begin
        Result := Value * Value;
      end,
      list);
    try
      for j in list2 do
        WriteLn(Format('map: %d', [j]));
      WriteLn(Format('reduce: %d', [
        TFuncTools<Integer>.Reduce(
          function (X, Y: Integer): Integer
          begin
            Result := X + Y;
          end,
          list2)
      ]));
    finally
      FreeAndNil(list2);
    end;
  finally
    FreeAndNil(list);
  end;
end.

TListをFreeしないといけないからうーん。

実行結果

>sample.exe
map: 1
map: 4
map: 9
map: 16
map: 25
reduce: 55

Pythonで書くとこんな感じか。

sample.py

#!/usr/bin/env python

def main():
    list2 = map(lambda value: value * value, range(1, 6))
    for i in list2:
        print 'map: %d' % i
    print 'reduce: %d' % reduce(lambda x, y: x + y, list2)

if __name__ == '__main__':
    main()