たとえば、次のようなポケモンオブジェクトのリストがあったとして:
[
{ name: 'Eevee', type: 'normal' },
{ name: 'Pidgeot', type: 'normal' },
{ name: 'Pikachu', type: 'electric' },
{ name: 'Raichu', type: 'electric' },
{ name: 'Jigglypuff', type: 'normal' },
{ name: 'Squirtle', type: 'water' },
{ name: 'Golduck', type: 'water' },
{ name: 'Voltorb', type: 'electric' }
]
これをタイプ別にグループ化したリストのリストをつくる関数を考えます。
まず、ポケモンオブジェクトをつくる関数:
const toPokemon = (name, type)=> {
return {
name: name,
type: type};
};
この関数を使って、実験対象となるポケモンリスト生成:
const pokemonlist = [
toPokemon('Eevee', 'normal'),
toPokemon('Pidgeot', 'normal'),
toPokemon('Pikachu', 'electric'),
toPokemon('Raichu', 'electric'),
toPokemon('Jigglypuff', 'normal'),
toPokemon('Squirtle', 'water'),
toPokemon('Golduck', 'water'),
toPokemon('Voltorb', 'electric')];
console.log(pokemonlist);
このポケモンリストを先頭から順番に調べて、タイプが同じだったらグループ化する再帰関数を作成:
const toNestedList = (pokemons, acc)=>{
if(pokemons.length<1){
return acc;
}
else {
const pokemon = head(pokemons);
const tailPokemons = tail(pokemons);
const nestedPokemons = last(acc);
if( nestedPokemons==null ){
acc.push([pokemon]);
}
else {
if( nestedPokemons[0].type == pokemon.type ){
nestedPokemons.push(pokemon);
}
else {
acc.push([pokemon]);
}
}
return toNestedList(tailPokemons, acc);
}
};
この toNestedList で使用する補助関数 head, tail, last 関数を作成:
const head = (list)=>{
if(list.length<1){
return null;
}
else {
return list[0];
}
};
const tail = (list)=>{
return list.slice(1);
};
/*
const tail = (list)=>{
if(list.length<2){
return [];
}
else {
const newList = [];
for(var i=1; i<list.length; i++){
newList.push(list[i]);
}
return newList;
}
};
*/
const last = (list)=>{
if(list.length<1){
return null;
}
else {
return list[list.length-1];
}
};
toNestedList を使ってタイプ別のリストのリストを作成:
const pokemonListListByType = toNestedList(pokemonlist, []);
console.log(pokemonListListByType);
node pokemon.js として実行してみます。
[
[
{ name: 'Eevee', type: 'normal' },
{ name: 'Pidgeot', type: 'normal' }
],
[
{ name: 'Pikachu', type: 'electric' },
{ name: 'Raichu', type: 'electric' }
],
[ { name: 'Jigglypuff', type: 'normal' } ],
[
{ name: 'Squirtle', type: 'water' },
{ name: 'Golduck', type: 'water' }
],
[ { name: 'Voltorb', type: 'electric' } ]
]
おっと、それなりにはグループ化できたのですが・・・ 順番にポケモンタイプを調べてサブグループ(ネストされたリスト)をつくるので、 toNestedList に与えるポケモンリストは、事前にタイプ別にソートされている必要がありました。
タイプ別にソートする関数 sortByType を作成:
const sortByType = (pokemons)=>{
return pokemons.sort( (pokemon0, pokemon1)=>{
return pokemon0.type.localeCompare(pokemon1.type);
});
};
localeCompare() とは?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
これを使って、再度出力してみます。
const pokemonListListByType = toNestedList( sortByType(pokemonlist), []);
console.log(pokemonListListByType);
node pokemon.js として実行:
[
[
{ name: 'Pikachu', type: 'electric' },
{ name: 'Raichu', type: 'electric' },
{ name: 'Voltorb', type: 'electric' }
],
[
{ name: 'Eevee', type: 'normal' },
{ name: 'Pidgeot', type: 'normal' },
{ name: 'Jigglypuff', type: 'normal' }
],
[
{ name: 'Squirtle', type: 'water' },
{ name: 'Golduck', type: 'water' }
]
]
うまくいきました。
pokemon.js:
const toPokemon = (name, type)=> {
return {
name: name,
type: type};
};
const pokemonlist = [
toPokemon('Eevee', 'normal'),
toPokemon('Pidgeot', 'normal'),
toPokemon('Pikachu', 'electric'),
toPokemon('Raichu', 'electric'),
toPokemon('Jigglypuff', 'normal'),
toPokemon('Squirtle', 'water'),
toPokemon('Golduck', 'water'),
toPokemon('Voltorb', 'electric')];
console.log(pokemonlist);
const head = (list)=>{
if(list.length<1){
return null;
}
else {
return list[0];
}
};
const tail = (list)=>{
return list.slice(1);
};
const last = (list)=>{
if(list.length<1){
return null;
}
else {
return list[list.length-1];
}
};
const toNestedList = (pokemons, acc)=>{
if(pokemons.length<1){
return acc;
}
else {
const pokemon = head(pokemons);
const tailPokemons = tail(pokemons);
const nestedPokemons = last(acc);
if( nestedPokemons==null ){
acc.push([pokemon]);
}
else {
if( nestedPokemons[0].type == pokemon.type ){
nestedPokemons.push(pokemon);
}
else {
acc.push([pokemon]);
}
}
return toNestedList(tailPokemons, acc);
}
};
const sortByType = (pokemons)=>{
return pokemons.sort( (pokemon0, pokemon1)=>{
return pokemon0.type.localeCompare(pokemon1.type);
});
};
//const pokemonListListByType = toNestedList(pokemonlist, []);
const pokemonListListByType = toNestedList( sortByType(pokemonlist), []);
console.log(pokemonListListByType);