normal کردن Data با استفاده از متد Reduce

اگر تا بحال سرو کارتون با redux یا هر state management دیگه‌ای افتاده باشه. حتما از normal کردن دیتا چیزی به گوش‌تون خورده. به طور کلی normal بودن یک data به این معنی هستش که میزان تو رفتگی داده‌ها انقدر نباشه که کار ما رو برای بروزرسانی، حذف و تغییر و حتی دسترسی به اون داد‌ه‌ها دچار مشکل کنه. البته که پکیج‌هایی هستند که این امکان رو به ما میدن که بتونیم دیتا بدیم و از طرفی normal شده تحویل بگیریم. اما اینجا من قصد دارم از با استفاده از متد Reduce برای normal کردن دیتا استفاده کنم.

از اینجا به بعد مقاله به جای واژه normal از واژه نرمال استفاده میکنم.

دیتای غیر نرمال چه شکلیه

به آبجکت پایینی نگاه کنید. برای اینکه بتونیم از فهرست غذا‌ها، فهرست غذا‌های خوشمزه رو داشته باشیم طبیعتا باید یک بار داخل آرایه category، چرخ بزنیم و هر بار هم چک کنیم فلان آیدی رو دیدی بهم خبر بده. این تازه بخش آسونه ماجراست. تصور کنید که بخوایم حالا از داخل آرایه food براساس categoryId لیست غذاهای اون catogory خاص رو داشته باشیم. میدونم سخته. به آپدیت کردنش که اصلا فکر نکنید :)

const data = {
  food: [
    {
      categoryId: "123",
      foods: ["ghorme, gheimeh, fesenjoon"],
    },
    {
      categoryId: "345",
      fruits: ["albaloo, anar, tootfarangi"],
    },
  ],

  category: [
    {
      id: "123",
      name: "delicious",
    },
    {
      id: "345",
      name: "fruits",
    },
  ],
}

قراره چیکار کنیم تا نرمال بشه؟ خب یه نگاهی به آبجکت پایینی بیندازید.

const food = {
  "123": {
    categoryId: "123",
    foods: ["ghorme, gheimeh, fesenjoon"],
  },
  "345": {
    categoryId: "345",
    fruits: ["albaloo, anar, tootfarangi"],
  },
}

همونطوری که میبینید الان ما آبجکتی به اسم food داریم که به راحتی میتونیم با چیزی شبیه به این foo['123'] تمام غذاهایی که categoryId اونها 123 هست رو ببینیم، تغییر بدیم و حتی حذف کنیم. تصورش رو بکنید اگه دیتایی که از سرور میگیریم رو به این شکل داخل store ذخیره کنیم چقدر کار ما ساده میشه.

Reduce چیه و چه شکلی کار میکنه؟

خب Reduce یکی از متدهاییه که آرایه‌های جاوااسکریپت به شما میدن. اما در مورد چطور کار کردنش پیشنهادم دیدن این لینک از کتاب eloquent هست. اینجا اومده یکبار Reduce رو به شکل تابع پیاده کرده و با خوندن این قطعه کد میتونید متوجه بشید که این تابع چطور کار میکنه.

اما به صورت کلی اگه reduce یک تابعی باشه با دو آرگومان، آرگومان ابتدایی یک تابع به شکل callback هست و آرگومان دوم تعیین کننده نقطه آغاز تابع reduce. این نقطه آغازین تا انتهای چرخش داخل آرایه با آرگومان اول تابع callback جایگزین (replace) میشه، البته اینکه چطور و به چه شکل این اتفاق بی‌افته رو ما با عملی که داخل callback مینویسیم تعیین میکنیم. برای نمونه میتونیم آرایه‌ای شامل اعداد یک تا ده داشته باشیم و جمع این اعداد رو به شکل زیر به راحتی به دست بیاریم.

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

const multi = arr.reduce((a, b) => {
  return a + b
}, 0)

console.log(multi) // 55

وقت نرمال کردنه

حالا قراره که یه آبجکت خالی رو با کلید‌‌‌های آیدی هر کدوم از آبجکت‌های داخل آرایه category پر کنیم. از آبجکت data که کمی پیش بالاتر تعریف کردیم، استفاده می‌کنیم. به قطعه کد زیر توجه کنید:

const category = data["category"]

const normalCategory = category.reduce((data, oldData) => {
  data[oldData.id] = oldData
  return data
}, {})

console.log(normalCategory)

اگر به قطعه کد بالا توجه کنید میبنید که آرگومان data هر بار با کلید آیدی oldData پر میشه و در نهایت data‌ی تازه، که نرمال هم شده return میشه. اما اگه قرار باشه ما همین کارو با آرایه food بکنیم و اینبار براساس categoryId نه براساس id، اونموقع باید چه کار کنیم؟ خب من برای حل این مشکل کار نرمال کردن رو به تابعی سپردم که یک آرایه میگیره و در صورت متغیر بودن کلیدی که قراره دیتا براساس اون نرمال بشه آرگومان دومی میتونه بگیره تا به واسطه اون جایگزین کلید پیشفرض Id بشه.

function normalizeDependOn(key, id = "id") {
  return key.reduce((data, oldData) => {
    data[oldData[id]] = oldData
    return data
  }, {})
}

حرف آخر

فارغ از اینکه کار نرمال کردن data رو با چه ابزاری انجام بدید، بدیهیه که این اتفاق کار شما رو برای عملیات روی داده‌ها بسیار ساده میکنه. اما خب برای من بشخصه تجربه‌ی جالبی هست که ببینم خیلی از ابزار‌ها چطور کارمیکنن یکی از اونها هم نرمالیزر بود که بعد از کند و کاو زیاد متوجه شدم میشه اینکارو با reduce انجامش داد. به همین جهت سعی کردم یاد گرفته‌های خودم رو با شما به اشتراک بگذارم. امیدوارم که مفید بوده باشه. قطعه کدی که دیدین از اینجا قابل دریافته.