0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[JavaScript] ObjectのfromEntriesとentriesを使って冗長な書き方を避ける

Posted at

tl;dr

以下のようなデータがあるとき、各値に対して* 5の計算をした結果を出したい。

const flavor = {
    umami:  0.1,
    amasa:  0.6,
    nigasa: 0.4,
}

しかし、キーごとに処理を書くと、キーがものすごく多い場合は困る。

flavor.umami * 5
flavor.amasa * 5
flavor.nigasa * 5

ObjectのentriesfromEntriesで解決する

const timeFive = Object.fromEntries(
    Object.entries(flavor)
    .map(([k, v]) => [k, v * 5])
)

メソッド紹介

以下のようなデータの出力結果を見ながらメソッドを理解してみましょう

const person = {
  name: "田中",
  age: 30,
  city: "東京"
};

entries

オブジェクトから、キーとバリューをとってきて配列にしてくれる

console.log(Object.entries(person));
// [["name", "田中"], ["age", 30], ["city", "東京"]]

fromEntries

entriesで出力する配列をオブジェクト化してくれる

const entries = [["name", "田中"], ["age", 30], ["city", "東京"]];
console.log(Object.fromEntries(entries));
// { name: "田中", age: 30, city: "東京" }

応用

このメソッドを利用すると以下のようなこともできる!

ケース1: オブジェクトの値を一括変換

const prices = { apple: 100, banana: 200, orange: 150 };
const discountedPrices = Object.fromEntries(
  Object.entries(prices)
    .map(([item, price]) => [item, price * 0.9])
);
// { apple: 90, banana: 180, orange: 135 }

ケース2: キーと値を入れ替える

const colors = { red: "#FF0000", blue: "#0000FF", green: "#00FF00" };
const reversed = Object.fromEntries(
  Object.entries(colors)
    .map(([name, code]) => [code, name])
);
// { "#FF0000": "red", "#0000FF": "blue", "#00FF00": "green" }

ケース3: 条件に基づくフィルタリング

const scores = { math: 85, english: 65, science: 90 };
const highScores = Object.fromEntries(
  Object.entries(scores)
    .filter(([_, score]) => score >= 80)
);
// { math: 85, science: 90 }

ケース4: ネストされたオブジェクトの処理

const users = {
  user1: { name: "田中", age: 30 },
  user2: { name: "佐藤", age: 25 }
};

const processedUsers = Object.fromEntries(
  Object.entries(users).map(([id, data]) => [
    id,
    { ...data, ageGroup: data.age >= 30 ? "シニア" : "ジュニア" }
  ])
);

// オブジェクトのバリデーション
const validateUserData = obj => Object.fromEntries(
  Object.entries(obj).map(([key, value]) => [
    key,
    typeof value === "string" ? value.trim() : value
  ])
);

TypeScriptとの相性

1. 型安全な変換処理

asでキーと値の型を明示的に定義することができる

interface Flavor {
  umami: number;
  amasa: number;
  nigasa: number;
}

const flavor: Flavor = {
  umami: 0.1,
  amasa: 0.6,
  nigasa: 0.4,
};

// 型を保持したまま変換
const timeFive = Object.fromEntries(
  Object.entries(flavor).map(([k, v]) => [k, v * 5])
) as Flavor;

2. ユーティリティ型との組み合わせ

Record型を使用すると、動的なキーを持つオブジェクトを定義できる。

type ScoreRecord = Record<string, number>;

const scores: ScoreRecord = {
  math: 85,
  english: 65,
  science: 90,
};

// 型安全な値の変換
const normalizedScores = Object.fromEntries(
  Object.entries(scores).map(([subject, score]) => [
    subject,
    Math.min(100, score)
  ])
) as ScoreRecord;

3. カスタム型ガード付きフィルタリング

ほしい型のデータだけを絞り込むこともできる!

interface UserData {
  name: string;
  age: number;
  email?: string;
}

type UserRecord = Record<string, UserData>;

const users: UserRecord = {
  user1: { name: "田中", age: 30 },
  user2: { name: "佐藤", age: 25, email: "sato@example.com" }
};

// メールアドレスを持つユーザーのみをフィルタリング
const hasEmail = (user: UserData): boolean => typeof user.email === "string";

const usersWithEmail = Object.fromEntries(
  Object.entries(users)
    .filter(([_, userData]) => hasEmail(userData))
) as UserRecord;

4. 型変換に伴う処理

安全に型変換をするときに使うこともできる。

interface RawUserData {
  name: string;
  age: string; // 最初は文字列として受け取る
}

interface ProcessedUserData {
  name: string;
  age: number; // 数値に変換
}

// 型変換を行うユーティリティ関数
const processUserData = (data: RawUserData): ProcessedUserData => ({
  name: data.name,
  age: parseInt(data.age, 10)
});

const rawUsers: Record<string, RawUserData> = {
  user1: { name: "田中", age: "30" },
  user2: { name: "佐藤", age: "25" }
};

// 型変換を適用
const processedUsers = Object.fromEntries(
  Object.entries(rawUsers)
    .map(([id, data]) => [id, processUserData(data)])
) as Record<string, ProcessedUserData>;

おわりに

最初は短い書き方がしたくて調べていたけど、使い道が多そうでもっとプログラムに取り入れていきたいと思った。
パフォーマンス的にはObject.keysを使った方がいい場面も多そうなのでそのへんについてもっと調べていきたいな。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?