for文を使わないで配列を活用する方法2つ

リスト型、配列型など同じようなデータを「かたまり」で扱う方法として
昔からfor文があります。

for(var i = 0; i < array.length; i++){
}

しかしながら、プログラムの基本であるところのforの出番が最近減ってきて
代わりに配列に使う関数ををよく見るようになりました。

理由を実感からあげるとすると、「配列に使う関数」のほうが、
書きやすく・読みやすいコードになるため、
多くの人が使っているのではと考えています。

事実としては、新しい言語なら「配列に使う関数」がすでに実装済みで、
昔からある言語でもバージョンアップで追加されてきました。

また、その種類も豊富になりつつあります。

今回はその中でも汎用性が高い2つの「配列に使う関数」を
javascriptで紹介しますが、javascriptが本業でない方でも、
他の言語でも似た機能がありますので参考になると思います。

  • for + ifの機能をもつfilter()
  • 配列から別の配列にするときに使うmap()

では一つずつみていきましょう。

for + ifの機能をもつfilter()

プログラムでfor文を扱うときは、配列のように同じような
データの「かたまり」のときです。

特に「かたまり」の中からある条件のものだけ取り出したときは、
if文と組み合わせて抽出します。

const students = [{age : 9 , name : 'suzuki'},
		{age : 5 , name : 'tanaka'},
		{age : 11, name : 'saito'}];
const result = students.filter(student => student.age >= 6);
console.log(result);
//output: [ { age: 9, name: 'suzuki' }, { age: 11, name: 'saito' } ]

https://paiza.io/ja/projects/new?language=javascript
こちらで実行できるのでお試しください。
最近ではブラウザでコードを気軽に実行できるサービスが増えてきましたね。

for文で表現するとこんな感じ。

const students = [{age : 9 , name : 'suzuki'},
		{age : 5 , name : 'tanaka'},
		{age : 11, name : 'saito'}];
var result = [];
for(var i =0; i < students.length;i++){
	if(students[i].age >= 6){
		result.push(students[i]);
	}	
}
console.log(result);
//output: [ { age: 9, name: 'suzuki' }, { age: 11, name: 'saito' } ]

3人の生徒の名前と年齢のデータなのですが、
6歳以上の生徒を取得するコードですね

const result = students.filter(student => student.age >= 6);

は、配列をフィルターの条件に一致するものだけにするという意味です。

かなりシンプルになっているのではないでしょうか。

for + if文にあった result.push(students[i]);

という「配列に入れる」という処理もなくなりコードがスッキリします。

しかし、スッキリするだけではなく、逆に疑問も出てきます。

  • 「student」どっから出てきた??
  • 「=>」って何??

ということで、「student => student.age >= 6」の部分を
掘り下げていきましょう。

「student =>」は配列のなかのひとつを指している

読み方ですが「=>を含めた左」と「右」で分けて読みます。

「student =>」と「student.age >= 6」ですね。

まずは「student=>」ですがfor of文に出てくる
「var student」に相当します。

for(var student of students){
}

javascript以外ではforeachステートメントという名前で使われているかもです。

つまりは「student =>」studentsの中のひとつを指しています。

filter()の中の「=>」より右はif文と一緒

すでに理解されているかもしれませんが、改めて。

「student.age >= 6」はif文の条件式に相当し、

一致したものだけがfilter()によって残されますという意味になります。

filter()はクエリのwhere句と似た機能をもつと
想像していただくのも良いかもしれません。

「student => student.age >= 6」のような書き方はほかの言語でも出てくる

「student => student.age >= 6」はjavascriptの書き方ですが、
同じ書き方、似た書き方で多くの言語で実装されてきています。

java,C#,ruby,rust, .etc

つまりこのfilterで使われる考え方、書き方は
新しい言語を学習したとしても使える資産になります。

配列から別の配列にするときに使うmap()

次はリストと配列に対して有用な関数map()を紹介したいと思います。

map()はjavascriptの関数ですが、もちろん他の言語にも
似た機能がありますので探してみてください。

ただ、名前は違うかもしれません。

ではサンプルです。

「生徒」の配列から「名前」だけの配列にします。

const students = [
	{age : 9 , name : "suzuki"},
	{age : 5 , name : "tanaka"},
	{age : 11, name : "saito"}];
const result = students.map(student => student.name)
console.log(result);
//output: [ 'suzuki', 'tanaka', 'saito' ]

const result = students.map(student => student.name)

studentsのなかから一行をとりだしてnameだけにします。

やっていることは

var result = [];
for (var i = 0; i < student.length ; i++){
	result.push(students[i].name);
}

ですね。

また、別の配列への変換はmap()の中で指定することでできます。

const result = students.map(student => ({name :student.name, country : "japan"}))

この例では、年齢がなくなり名前と「country : “japan”」をもつ

配列ができあがります。

filter()はクエリのwhere句のようでしたが、
map()はのselect句のような特徴をもっていますね。

filter()とmap()の合わせ技

紹介したfilter()とmap()は一緒に使うことができます。

const result = students.filter(student => student.age >= 6)
                .map(student => student.name)
//output [ 'suzuki', 'saito' ]

いかがでしょう。

スッキリしてますし、日本語としても
「年齢が6才以上の生徒の名前を取得」していると読めるので

理解しやすいコードになっていないでしょうか。

まとめ

for文の代わりに使う関数は以上になります。

コードの書き方が特徴的なので一度書き方を覚えないと
「なんだこのコード?」ってなります。

それに、for文という馴染みのあるコードがあるため、
「わざわざ別の書き方をしなくても良いじゃないか」という意見もあります。

しかし、それでも多くの言語に実装されていることを鑑みるに、
有用な仕組みだと考えられないでしょうか。

今回紹介した関数は二つでしたが他にもたくさんあります。
重複排除したり、言語によっては、合計/平均/最大/最小のように
集計できたり機能豊富です。

もし「配列に使う関数」興味をもっていただけたら、
是非コーディングにつかってみてはどうでしょうか。