🙄
JavaScriptでネストしたオブジェクトから、キーワード検索
ネストしたオブジェクトから値を取得するにはどうするのか?
仕事で配列を操作して値を取得するロジックを実装する場面があった。意外と難しかった。入れ子構造になってるオブジェクトから値をキーワード検索で取得する。
let companies = [
{
id: 1,
name: '株式会社A',
member: {
age: 20,
count: 500,
},
place: 'TOKYO'
},
{
id: 2,
name: '株式会社B',
member: {
age: 25,
count: 300,
},
place: 'OSAKA'
},
{
id: 3,
name: '株式会社C',
member: {
age: 20,
count: 500,
},
place: 'TOKYO'
}
];
const filterByKeyword = (companies, keyword) => {
return companies.filter(company => {
return Object.values(company).some(value => {
if (typeof value === 'object') {
return Object.values(value).includes(keyword);
}
return value === keyword;
});
});
};
let result = filterByKeyword(companies, 'TOKYO');
console.log(result);
result = filterByKeyword(companies, 20);
console.log(result);
このコードでは、以下の手順を踏んでいます:
- 会社のデータを配列として管理します。
- filterByKeyword 関数を定義し、指定したキーワードに基づいて会社をフィルタリングします。
- filterByKeyword 関数を呼び出し、TOKYO または 20 に一致する会社を検索して結果をログに出力します。
この方法で、指定したキーワードに一致する会社の情報を抽出できます。
こちらのメソッドの知識が必要だった。公式の解説を読んでもらった方がいいと思うので、解説はしません。
filterの書き方にもパターンがあった
2個のパターン。これは良くないらしい?
1個にまとめた方がいいとか。
// ネストしたオブジェクト
let account = {
name: "Mike",
age: 25,
expenses: {
food: 100,
rent: 300,
insurance: 200,
},
income: 1000,
};
const searchFitter = (account, key, minValue) => {
// expensesオブジェクトを配列に変換
const expensesArray = Object.entries(account.expenses);
// filterをドットで繋げて使用
const result = expensesArray
.filter(([k, v]) => k === key)
.filter(([k, v]) => v > minValue);
// 結果をオブジェクトに戻す
const filteredExpenses = Object.fromEntries(result);
return filteredExpenses;
};
let result = searchFitter(account, "rent", 200);
console.log(result); // { rent: 300 }
1個にまとめたパターン。仕事のコードは丸かっこで囲んだのがあったので、&&とかで、2つ処理かけなかったような???
// ネストしたオブジェクト
let account = {
name: 'Mike',
age: 25,
expenses: {
food: 100,
rent: 300,
insurance: 200
},
income: 1000
};
const searchFitter = (account, key, value) => {
const expensesArray = Object.entries(account.expenses);
expensesArray.filter(([key, value]) => key === 'rent' && value > 200);
const filteredExpenses = Object.fromEntries(result);
return filteredExpenses;
};
// expensesオブジェクトを配列に変換
const expensesArray = Object.entries(account.expenses);
// filterを1回だけ使用して、指定した条件に一致する項目を抽出
const result = expensesArray.filter(([key, value]) => key === 'rent' && value > 200);
// 結果をオブジェクトに戻す
const filteredExpenses = Object.fromEntries(result);
console.log(filteredExpenses); // { rent: 300 }
Reactでも配列の検索ができる機能を作ってみた。意外と難しいですね。もっと複雑なロジックを実装していた気がする。
import React, { useState, useEffect } from 'react';
import { FaSearch } from 'react-icons/fa'; // react-icons ライブラリを使用
interface Company {
id: number;
name: string;
member: {
age: number;
count: number;
};
place: string;
}
const companies: Company[] = [
{
id: 1,
name: '株式会社A',
member: {
age: 30,
count: 100,
},
place: 'OSAKA'
},
{
id: 2,
name: '株式会社B',
member: {
age: 25,
count: 200,
},
place: 'KYOTO'
},
{
id: 3,
name: '株式会社C',
member: {
age: 20,
count: 500,
},
place: 'TOKYO'
}
];
const filterByKeyword = (companies: Company[], keyword: string | number): Company[] => {
return companies.filter(company => {
return Object.values(company).some(value => {
if (typeof value === 'object' && value !== null) {
return Object.values(value).some(subValue => {
if (typeof subValue === 'string' || typeof subValue === 'number') {
return subValue.toString().includes(keyword.toString());
}
return false;
});
}
if (typeof value === 'string' || typeof value === 'number') {
return value.toString().includes(keyword.toString());
}
return false;
});
});
};
const Filter: React.FC = () => {
const [keyword, setKeyword] = useState<string | number>('');
const [filteredCompanies, setFilteredCompanies] = useState<Company[]>(companies);
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Enter') {
setFilteredCompanies(filterByKeyword(companies, keyword));
}
};
// Enter キーを押したときに検索を実行
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [keyword]);
const handleSearchClick = () => {
setFilteredCompanies(filterByKeyword(companies, keyword));
};
return (
<div>
<input
type="text"
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
placeholder="キーワードを入力"
/>
<button onClick={handleSearchClick}>
<FaSearch />
</button>
<ul>
{filteredCompanies.map(company => (
<li key={company.id}>
{company.name} - {company.place}
{company.member.age}歳 {company.member.count}人
</li>
))}
</ul>
</div>
);
};
export default Filter;
感想
配列の操作は難しいですね😅
他にも検索する方法は複数あります。リンク載せておきます。
Discussion
普通のJavaScriptの場合
検索機能を作ってみた。
TypeScrtiptの場合
node.jsで実行するだけですが、データ型をつけた方が、どのデータ型なのかコードジャンプで確認できるので、便利でしたね。そのままのJavaScriptだと、エラーとか出ませんし😅