📘
配列処理の問題集(JavaScript)
はじめに
JavaScript
の配列処理による問題を作成しました。またコードはTypeScript
で書いています。
問題は随時追加予定です!
(追記)
2020/11/14 問題㉑
2020/11/15 問題㉒
2020/11/30 問題㉓
2021/ 5/ 5 問題㉔
問題①
1から100までの数字が格納された配列の作成をして下さい。
解答
const arry = [...new Array(101 - 1).keys()].map((n) => n + 1);
//[...new Array(101 - 1).keys()]だけだと0~99までの配列となるため、mapメソッドで調整
//別解
const array = Array.from({ length: 100 }, (_, i) => i + 1);
問題②
次の連想配列(images)のheightだけを取得し、新しい配列(heights)を作成して下さい。
type Images = {
height: string;
width: string;
}[];
const images: Images = [
{ height: "20px", width: "40px" },
{ height: "34px", width: "56px" },
{ height: "28px", width: "64px" },
];
解答
const heights = images.map(({ height }) => {//オブジェクトの分割代入の利用
return height;
});
//省略記法
const heights = images.map(({ height }) => height);
//別解
const heights = images.reduce((acc, cur, i) => {
acc[i] = cur.height;
return acc;
}, []);
問題③
次の連想配列(member)の中から名前(name)の値だけを抜き取った配列が返るような関数getNameを作成して下さい。
type Members = {
name: string;
age: number;
gender: "male" | "female";
}[];
const members: Members = [
{ name: "松井", age: 39, gender: "male" },
{ name: "今田", age: 34, gender: "female" },
{ name: "鈴木", age: 24, gender: "male" },
{ name: "山田", age: 56, gender: "male" },
{ name: "田中", age: 89, gender: "female" },
];
解答
type GetName<T extends Members, U> = (array: T) => U[];
const getName: GetName<Members, string> = (array) => {
return array.map(({ name }) => name);
};
console.log(getName(members));
//["松井", "今田", "鈴木", "山田", "田中"]
問題④
以下の連想配列(users)の中から、管理者権限(admin)を持っている(true)ユーザーに絞り込み、filteredUsersという変数に格納して下さい。
type Users = {
id: number;
admin: Boolean;
}[];
const users: Users = [
{ id: 1, admin: true },
{ id: 2, admin: true },
{ id: 3, admin: false },
{ id: 4, admin: true },
{ id: 5, admin: false },
];
解答
const filteredUsers = users.filter(({ admin }) => admin);
console.log(filteredUsers)
//[
// { id: 1, admin: true },
// { id: 2, admin: true },
// { id: 4, admin: true }
//]
問題⑤
次の多次元配列のインデックス0番目のみを取り出した配列を作成して下さい。
const array = [
["Ruffy", "captain"],
["Zoro", "combatant"],
];
解答
const arry = array.map((key) => key[0]);
console.log(arry); //["Ruffy", "Zoro"]
問題⑥
次の多次元配列の0番目の配列のみを取り出し新しい配列に作成して下さい。
const array = [
["Ruffy", "captain"],
["Zoro", "combatant"],
];
解答
const arr = array.filter((key, i) => {
if (i === 0) {
return key;
}
});
//別解
const arr = array.filter((_, index) => index === 0)
console.log(arr); //["Ruffy", "captain"]
問題⑦
次の連想配列(member)の中から35歳以上の名前(name)の値だけを抜き取った配列が返るような関数getNameOver35を作成して下さい。
type Members = {
name: string;
age: number;
gender: "male" | "female";
}[];
const members: Members = [
{ name: "松井", age: 39, gender: "male" },
{ name: "今田", age: 34, gender: "female" },
{ name: "鈴木", age: 24, gender: "male" },
{ name: "山田", age: 56, gender: "male" },
{ name: "田中", age: 89, gender: "female" },
];
解答
type GetNameOver35<T extends Members, U> = (array: T) => U[];
const getNameOver35: GetNameOver35<Members, string> = (array) => {
return array.filter(({ age }) => age > 35).map(({ name }) => name);
};
console.log(getNameOver35(members));
//["松井", "山田", "田中"]
問題⑧
以下のような重複値を含む配列arrの中から、重複値を除く互いに素な配列を作成して下さい。
const arr = [2, 4, 7, 5, 4];
解答
const coprimeArr = [...new Set(arr)];//[2, 4, 7, 5]
//別解
const coprimeArr = arr.filter((num, i, arrr) => {
return arrr.indexOf(num) === i;
});//[2, 4, 7, 5]
問題⑨
次の連想配列の中からnameプロパティをもったユーザーに絞り込み、getNameという変数に格納して下さい。
interface User {
id: number;
name?: string;
}
const users: User[] = [
{ id: 1, name: "豊臣" },
{ id: 2 },
{ id: 3, name: "織田" },
];
解答
const getName = users
.filter((user: User) => "name" in user)
//別解
const getName = users.filter(({ name }) => name);
問題⑩
以下の連想配列(users)の中から、管理者権限(admin)を持っている(true)ユーザーを探し、最初に見つけた(true)ユーザーをadminという変数に格納して下さい。
expect: { id: 2, admin: true }
type Users = {
id: number;
admin: Boolean;
}[];
const users: Users = [
{ id: 1, admin: false },
{ id: 2, admin: true },
{ id: 3, admin: false },
{ id: 4, admin: true },
];
解答
const admin = users.find(({ admin }) => admin);
//別解
const admin = users.filter(({ admin }) => admin)[0]
問題⑪
次の連想配列(member)の中から,田中さんのオブジェクトを抽出するfindTanakaという関数,変数を作成しなさい。
expect: {name: "田中", age: 89, gender: "female"}
type Members = {
name: string;
age: number;
gender: "male" | "female";
}[];
const members: Members = [
{ name: "松井", age: 39, gender: "male" },
{ name: "今田", age: 34, gender: "female" },
{ name: "鈴木", age: 24, gender: "male" },
{ name: "山田", age: 56, gender: "male" },
{ name: "田中", age: 89, gender: "female" },
];
解答
const findTanaka = (array: Members) => {
return array.find(({ name }) => name === "田中");
};
//別解
const findTanaka = members.members.slice(-1)[0];
使用メソッド
問題⑫
アンケートを実施した結果がusersという連想配列に格納されています。ユーザー全員が回答済みかどうかを確認し、hasSubmitted変数に結果(trueかfalse)を示して下さい。
expect: false
type Users = {
id: number;
hasSubmitted: boolean;
}[];
const users: Users = [
{ id: 2, hasSubmitted: true },
{ id: 3, hasSubmitted: false },
{ id: 4, hasSubmitted: true },
];
解答
問題⑬
次のtripという連想配列に格納されたdistanceの合計を求めて、totalDistanceという変数に格納して下さい。
type Trips = { distance: number }[];
const trips: Trips = [{ distance: 34 }, { distance: 12 }, { distance: 1 }];
解答
const totalDistance = trips.reduce((sum, trip) => {
return trip.distance + sum;
}, 0);
console.log(totalDistance);//47
//分割代入
const totalDistance = trips.reduce((sum, { distance }) => {
return distance + sum;
}, 0);
console.log(totalDistance); //47
使用メソッド
問題⑭
次の変数engineersに格納されたエンジニアの種類(フロントエンド、バックエンド)の数を種類を集計し、一つのオブジェクトに格納して下さい。
type Engineers = { type: 'Frontend' | 'Backend' }[]
const engineers: Engineers = [
{ type: 'Frontend' },
{ type: 'Backend' },
{ type: 'Backend' },
{ type: 'Frontend' },
{ type: 'Frontend' },
{ type: 'Backend' },
{ type: 'Backend' }
]
expect: {Frontend: 3, Backend: 4}
解答
const engineerType = engineers.reduce(
(sum, { type }) => {
if (type === 'Frontend') {
sum.Frontend++
} else {
sum.Backend++
}
return sum
},
{ Frontend: 0, Backend: 0 }
)
問題⑮
次の変数objを連想配列[{A:'a'},{B:'b'}]にして下さい。
const obj = {
a: "A",
b: "B",
};
解答
問題⑯
次の変数arrをオブジェクト{a:"0", b:"1"}にして下さい。
const arr = ["a", "b"];
解答
type Alpha = {
[alpha: string]: string;
};
const obj:Alpha = arr.reduce((prev, curr, i) => {
return { ...prev, [curr]: `${i}` };
}, {});//引数のprevの挙動をコンソール上で確認すると理解が深まります!
問題⑰
次の変数fruitsの中から"みかん"、"ぶどう"をキーに持つオブジェクトのみを抽出し、新しい変数selectFruitsに格納して下さい。
type Fruitsobj = {
price: number;
num: number;
};
type Fruits = {
[fruit: string]: Fruitsobj;
};
const fruits: Fruits = {
みかん: { price: 200, num: 5 },
いちご: { price: 400, num: 1 },
ぶどう: { price: 380, num: 7 },
};
解答
const arr = Object.entries(fruits);
const arrr = arr.filter((key) => {
return key[0] === "みかん" || key[0] === "ぶどう";
});
const selectFruits = arrr.reduce((prev, [k, v]) => {
return { ...prev, [k]: v };
}, {});
//ぶどう: {price: 380, num: 7}
//みかん: {price: 200, num: 5}
//別解(class表記)
type Fruits = 'みかん' | 'ぶどう' | 'いちご'
class SelectFruits {
fruitsArray: [string, Fruitsobj][]
constructor(
public allFruits: IFruits,
public fruit1: Fruits,
public fruit2: Fruits
) {
this.fruitsArray = Object.entries(this.allFruits)
}
filter() {
this.fruitsArray = this.fruitsArray.filter(
key => key[0] === this.fruit1 || key[0] === this.fruit2
)
return this
}
reduce() {
const selectFruits = this.fruitsArray.reduce((prev, [k, v]) => {
return { ...prev, [k]: v }
}, {})
return selectFruits
}
}
const orangeAndGrape = new SelectFruits(fruits, 'みかん', 'ぶどう')
console.log(orangeAndGrape.filter().reduce())
問題⑱
次の配列の中で一番大きい値を求めて下さい。
const array = [40, 100, 300, 50];
expect: 300
解答
const result = array.reduce((acc, cur) => {
return acc > cur ? acc : cur;
});//300
//別解(applyメソッドの利用)
const result1 = Math.max.apply(null, array);
//別解(スプレッド構文の利用)
const result2 = Math.max.(...array);
//別解
function result3(array: number[]) {
let tempArr = array.sort((a, b) => {
return a - b;
});
let largest = tempArr.pop();
return largest;
}
console.log(result3(array));//300
問題⑲
次のJsonJson形式の変数complexJsonから"ハンバーグ"の要素だけ取り出し、配列でラップして下さい。
type ComplexJson = {
[food: string]: { 分類: string; 主成分: string | object };
};
const complexJson: ComplexJson = {
ハンバーグ: {
分類: "洋食",
主成分: "タンパク質",
},
カレー: {
分類: "洋食",
主成分: {
ルー: "タンパク質",
ライス: "炭水化物",
},
},
親子丼: {
分類: "和食",
主成分: {
具: "タンパク質",
ご飯: "炭水化物",
},
},
};
expect [ハンバーグ: {分類: "洋食", 主成分: "タンパク質"}]
解答
const entriesArray = Object.entries(complexJson)
const arr = entriesArray.reduce((acc, cur) => {
if (cur[0] === "ハンバーグ") {
return [{ ...acc, [cur[0]]: cur[1] }];
}
return acc;
}, []);
//別解(クラス記法)
class SelectFood {
foodArray: [
string,
{
分類: string
主成分: string | object
}
][]
constructor(public foodObj: ComplexJson, public food: string) {
this.foodArray = Object.entries(this.foodObj)
}
reduce() {
this.foodArray = this.foodArray.reduce((acc, cur) => {
if (cur[0] === 'ハンバーグ') {
return [{ ...acc, [cur[0]]: cur[1] }]
}
return acc
}, [])
return this.foodArray
}
}
const ham = new SelectFood(complexJson, 'ハンバーグ')
console.log(ham.reduce())
問題⑳
次の連想配列のオブジェクトのキー名を"0"→"id"、"1"→"shop"に変更して下さい。
const srcData = [
{ 0: 'id1', 1: '店A' },
{ 0: 'id2', 1: '店B' },
{ 0: 'id3', 1: '店C' }
]
expect: [
{ id: 'id1', shop: '店A' },
{ id: 'id2', shop: '店B' },
{ id: 'id3', shop: '店C' }
]
解答
const newSrcData = srcData.reduce((acc, cur) => {
return [...acc, { id: cur[0], shop: cur[1] }]
}, []
問題㉑
次の連想配列の果物の詳細が書かれた各オブジェクトから'totalItems'(個数の合計),'cartTotal'(合計金額)をプロパティにもつ連想配列を作成してください。
type Cart = {
item: string
price: number
amount: number
}[]
const cart: Cart = [
{
item: 'いちご',
price: 150,
amount: 3
},
{
item: 'みかん',
price: 250,
amount: 3
},
{
item: 'ぶどう',
price: 300,
amount: 2
}
]
expect: [ { totalItems: 8, cartTotal: 700 } ]
解答
const total = cart.reduce(
(total, { amount, price }) => {
total[0]['totalItems'] += amount
total[0]['cartTotal'] += price
return total
},
[
{
totalItems: 0,
cartTotal: 0
}
]
)
問題㉒
次の1~30までの数字が格納された配列'item'を10分割、14分割した二次元配列'newItems1','newItems2'を作成してください。
const item = Array.from({ length: 30 }, (_, index) => {
return index + 1;
});
解答
const itemPerPage1 = 10;
const itemPerPage2 = 14;
const pages = (itemPer: number) => {
return Math.ceil(item.length / itemPer);
};
const newItems1 = Array.from({ length: pages(itemPerPage1) }, (_, index) => {
const start = index * itemPerPage1;
const tempItems = item.slice(start, start + itemPerPage1);
return tempItems;
});
const newItems2 = Array.from({ length: pages(itemPerPage2) }, (_, index) => {
const start = index * itemPerPage2;
const tempItems = item.slice(start, start + itemPerPage2);
return tempItems;
});
console.log(newItems1);//[ [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], [ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ], [ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ] ]
console.log(newItems2);//[ [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ], [ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 ], [ 29, 30 ] ]
//別解
const chunk = (arr: number[], num: number) => {
return arr.reduce(
(a, e, i) =>
i % num
? [...a.slice(0, a.length - 1), [...a[a.length - 1], e]]
: [...a, [e]],
[]
)
}
console.log(chunk(item, 10))
console.log(chunk(item, 14))
問題㉓
次の連想配列(member)の中から,鈴木さんを同僚、松井さんと今田さんを後輩として関係を区別してください。
type Members = {
name: string;
age: number;
gender: "male" | "female";
}[];
const members: Members = [
{ name: "松井", age: 21, gender: "male" },
{ name: "今田", age: 23, gender: "female" },
{ name: "鈴木", age: 27, gender: "male" },
{ name: "山田", age: 33, gender: "male" },
{ name: "田中", age: 35, gender: "female" },
];
解答
for (let i = 0; i < members.length; i++) {
const element = members[i];
if (element['name'] === '鈴木') {
console.log(`${element['name']} is my colleague`);//鈴木 is my colleague
break;//continue であれば山田さん、田中さんのオブジェクトが取れる。
}
console.log(`${element['name']} is my junior coworker`);
//松井 is my junior coworker
//今田 is my junior coworker
}
問題㉔
引数に奇数、偶数を順に受け取り、返り値として自然数を順に並べた配列を返す関数(getNaturalNumber)を作成してください。
console.log(getNaturalNumber([1, 3, 5], [2, 4, 6]))
// [1,2,3,4,5,6]
解答
const getNaturalNumber = (odd: number[], even: number[]) => {
const NaturalNumber: number[] = []
while (odd[odd.length - 1] || even[even.length - 1]) {
// 条件処理における || はどちらか片方が真であれば全体として真を返す
if (even[even.length - 1]) {
NaturalNumber.unshift(even.pop())
}
if (odd[odd.length - 1]) {
NaturalNumber.unshift(odd.pop())
}
}
return NaturalNumber
}
//別解(クラス記法)
class GetNaturalNumber {
constructor(public odd: number[], public even: number[]) {}
getNaturalNumber() {
const num = []
while (this.odd[this.odd.length - 1] || this.even[this.even.length - 1]) {
// 条件処理における || はどちらか片方が真であれば全体として真を返す
if (this.even[this.even.length - 1]) {
num.unshift(this.even.pop())
}
if (this.odd[this.odd.length - 1]) {
num.unshift(this.odd.pop())
}
}
return num
}
}
const num = new GetNaturalNumber([1, 3, 5], [2, 4, 6])
console.log(num.getNaturalNumber()) //[1,2,3,4,5,6]
Discussion