post Image
様々な言語でMap, Filter, Reduceを実現してみた(1)

前書き

自分ルールの中で、慣れない言語に触れるときに必ずやっているのが、データドリブン的に「Map, Filter, Reduce」が素直に記述できるかを確かめること。

慣れない言語を触らなければならない時に「あれ、map, filter, reduceっぽいことどうやるんだっけ?」ってなった時のリファレンスになれば幸い。

(5/26修正)
タグが5つまでしか付けられないことに気がついたので、やはり記事を分離します。すでに6つ書いてしまっていたので、特にコメント等に言及されてなかったF#を(2)に移すことにしました。

実際にやってみた

処理概要

  1. 10,000,000件のデータを生成(整数値で0〜9,999,999の値が入っている)
  2. 各要素を2倍にする
  3. 3の倍数である数値のみ抽出
  4. 抽出後の要素を総和する

対象言語

  • C++ (C++11文法)
  • Python(v3)
  • Kotlin(v1.1.2)
  • Swift(v3)
  • Javascript (node v6.9.4)

環境

  • Mac Book Air (Early 2014)
  • macOS Sierra 10.12.4
  • Visual Studio Code (エディタ)

制限事項

  • 言語特有の裏技を駆使して最速を目指すのは避けた(自分の中では普通に書いたつもり)
  • 生成したデータはイテレータオブジェクトではなく、実体データの集合になるようにした
  • map, filter, reduce処理呼び出しについては続けて呼ぶような記述にした
  • 計算結果は全ての言語において33333336666666になっていることを確認済み
  • map処理の開始直前からreduce処理終了までの時間を参考までに計測した

コード

時間計測処理付きのコードはGithubに上げており、各言語のフォルダにあるmapFilterReduce.*ファイルを参照のこと。

C++
#include <vector>
#include <algorithm> // transform, copy_if
#include <iterator>  // back_inserter
#include <iostream>  // cout
#include <numeric>   // accumulate
using namespace std;

int main(){
    // 1. Generating sequence
    auto a = vector<long long>(10000000);
    for (long long i=0; i < a.size(); ++i) a[i] = i;

    // 2. Mapping the sequence into another
    auto mapped = vector<long long>(10000000);
    transform(a.begin(), a.end(), mapped.begin(), [](long long x){return x * 2;});
    // 3. Filtering the sequence
    vector<long long> filtered;
    copy_if(mapped.begin(), mapped.end(), back_inserter(filtered), [](long long x){return x%3==0;});
    // 4. Reducing the sequence
    long long result = accumulate(filtered.begin(), filtered.end(), (long long)0, [](long long a, long long b){return a+b;});
    // As a result
    cout << result << endl;
    return 0;
}
Python3
import functools            # for reduce function

# 1. Generating sequence
a = list(range(10000000))

# 2. Mapping the sequence into another (Defered execution)
mapped = map(lambda n:n*2, a)
# 3. Filtering the sequence (Defered execution)
filtered = filter(lambda n:n%3==0, mapped)
# 4. Reducing the sequence
result = functools.reduce(lambda a,b:a+b, filtered)
# As a result
print(result)
Kotlin
fun main(args:Array<String>){
   var a = 
        // 1. Generating sequence
        IntArray(10000000) { it }

    var result = 
        // 2. Mapping the sequence into another
        a.map { n -> n * 2}
        // 3. Filtering the sequence
        .filter { n -> n%3 == 0}
        // 4. Reducing the sequence
        .fold(0L) { x, y -> x.toLong() + y.toLong()}

    // As a result
    println(result.toString())
}
Swift
let a = 
    // 1. Generating sequence
    (0..<10000000)

let result =
    // 2. Mapping the sequence into another
    a.map {$0*2}
    // 3. Filtering the sequence
    .filter {$0 % 3 == 0}
    // 4. Reducing the sequence
    .reduce(0, +)

// As a result
print("\(result)")
Javascript
// 1. Generating sequence
var a = new Array(10000000);
for (var index = 0; index < a.length; index++) a[index] = index;
// 2. Mapping the sequence into another
var mapped = a.map(n=>n*2);
// 3. Filtering the sequence
var filtered = mapped.filter(n=>n%3==0);
// 4. Reducing the sequence
var result = filtered.reduce((a,b)=>a+b);
// As a result
console.log(result);

考察

一通り記述してみた感触として

  • C++は仕方ないにしろ大体同じような書き方で実現できることがわかった
  • 無名関数の書き方が様々で、慣れの問題な気がしてきた
  • 関数を繋げていけるものもあれば、できないものもある。

参考結果

計測値は揺らいでいたけど大体この前後ということで端数をカット。

言語 計測値(msec) 備考
C++ 90 -O3 付きでコンパイル
Python 5000
Kotlin 3500
Swift 150 -Ounchecked 付きでコンパイル
Javascript 11000 v6以外なら2000msecぐらいになる

※過去に計測したデータは編集履歴を見るとわかります。色々おかしかったところもありますが、良い勉強になりました。


『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。