Home About
Node.js , Underscore , Functional Programming

Node.js + Underscore でcountif を使って2つのリストから重複した要素のみのリストを作り出す

二つのリストから countif をつかって 両方のリストに重複して含まれている要素のみを取り出したリストをつくる.

これを Node.js + Underscore で実装した。(覚え書き)

package.json:

{
  "name": "countup",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "underscore": "^1.13.1"
  }
}

countif 関数:

const countif = (list, value)=>{
	return _.size( _.filter(list, (v)=> (v == value)) );
};

リストと値を引数にとり、リスト中にその値が何回出現するかを返す.

簡単なテストコードを記述すれば以下のようになる.

console.log( countif(['a','b','c','d'], 'c')); // -> 1
console.log( countif(['a','b','c','d'], 'z')); // -> 0
console.log( countif([1,2,3,1,2,3], 3)); // -> 2

コード全体ではこうなる.

countif.js:

const _ = require('underscore');

const countif = (list, value)=>{
	return _.size( _.filter(list, (v)=> (v == value)) );
};

console.log( countif(['a','b','c','d'], 'c')); // -> 1
console.log( countif(['a','b','c','d'], 'z')); // -> 0
console.log( countif([1,2,3,1,2,3], 3)); // -> 2

それでは、この countif を使って、2つのリストに重複する要素を取り出すコードを書いてみる。

方針は、以下の通り。

なお、各リスト内はユニーク(重複要素がない)を前提にしている。

index.js:

const _ = require('underscore');

const countif = (list, value)=>{
	return _.size( _.filter(list, (v)=> (v == value)) );
};

const createItem = (count, value)=> {
	return {
		count: count,
		value: value};
};

const listA = ['a','b','c','d'];
const listB = ['b','c','d','e','f'];

// 2つのリストを結合する.
const listAB = listA.concat( listB );

// reduce しながら、各要素の出現回数を記録する.
const itemList = _.reduce(listAB, (accumulator, itemValue)=> {
	const count = countif( _.map(accumulator, (it)=> it.value), itemValue);
	if( count>0 ){
		const targetItem = _.filter(accumulator, (it)=>(it.value==itemValue) )[0];
		return _.filter(accumulator, (it)=>(it.value!=itemValue) ).concat( [createItem(targetItem.count+1, targetItem.value)] );
	} else {
		return accumulator.concat( [ createItem(1,itemValue) ] )
	}
}, []);

// item.count==2 の要素のみを抽出した後、要素を item から 文字列 にしたリストをつくる.
const duplicatedList = _.map( _.filter(itemList, (it)=> (it.count==2) ), (it)=>it.value );

// 結果を出力(2つのリストのうち重複した文字列だけを出力).
console.log( duplicatedList );

実行する:

$ node index.js
[ 'b', 'c', 'd' ]