ساخت اندیس درون حافظه با جاوا اسکریپت – از صفر تا صد

۱۵۵
۱۴۰۲/۰۶/۷
۳ دقیقه
PDF
ساخت اندیس درون حافظه با جاوا اسکریپت – از صفر تا صدساخت اندیس درون حافظه با جاوا اسکریپت – از صفر تا صد
آموزش متنی جامع
امکان دانلود نسخه PDF

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

997696

فرض کنید می‌خواهید یک اپلیکیشن فروش آنلاین بسازید و به آرایه‌ای مانند زیر نیاز دارید:

1const skus = [
2  {
3    "productId": 1,
4    "colorId": 1,
5    "sku": "11-M"
6  },
7  {
8    "productId": 1,
9    "colorId": 1,
10    "sku": "11-L"
11  },
12  {
13    "productId": 1,
14    "colorId": 2,
15    "sku": "12-M"
16  },
17  {
18    "productId": 1,
19    "colorId": 2,
20    "sku": "12-L"
21  },
22  {
23    "productId": 2,
24    "colorId": 1,
25    "sku": "21-M"
26  },
27  {
28    "productId": 2,
29    "colorId": 1,
30    "sku": "21-L"
31  }
32];
مشاهده کامل کدها

با فرض آرایه فوق وظیفه شما این است که همه SKU-ها را برای یک productId خاص به دست آورید. نخستین چیزی که به ذهن می‌رسد، استفاده از کد زیر است:

1skus.find(s => productId === s.productId)

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

به این منظور از reduce استفاده می‌کنیم:

1const skus = [
2  {
3    "productId": 1,
4    "colorId": 1,
5    "sku": "11-M"
6  },
7  {
8    "productId": 1,
9    "colorId": 1,
10    "sku": "11-L"
11  },
12  {
13    "productId": 1,
14    "colorId": 2,
15    "sku": "12-M"
16  },
17  {
18    "productId": 1,
19    "colorId": 2,
20    "sku": "12-L"
21  },
22  {
23    "productId": 2,
24    "colorId": 1,
25    "sku": "21-M"
26  },
27  {
28    "productId": 2,
29    "colorId": 1,
30    "sku": "21-L"
31  }
32];
مشاهده کامل کدها

بنابراین کد به صورت زیر خواهد بود:

1const productIndex = indexByField(skus, “productId”);

اندیس نیز به صورت زیر درمی‌آید:

1{
2  "1": [
3    {
4      "productId": 1,
5      "colorId": 1,
6      "sku": "11-M"
7    },
8    {
9      "productId": 1,
10      "colorId": 1,
11      "sku": "11-L"
12    },
13    {
14      "productId": 1,
15      "colorId": 2,
16      "sku": "12-M"
17    },
18    {
19      "productId": 1,
20      "colorId": 2,
21      "sku": "12-L"
22    }
23  ],
24  "2": [
25    {
26      "productId": 2,
27      "colorId": 1,
28      "sku": "21-M"
29    },
30    {
31      "productId": 2,
32      "colorId": 1,
33      "sku": "21-L"
34    }
35  ]
36}
مشاهده کامل کدها

اینک می‌توانیم همه SKU-ها را برای یک محصول خاص به دست آوریم.

روش دستیابی به SKU-ها با رنگ خاص

همچنان که متوجه شدید در بخش قبل تنها آرایه خود را بر اساس productId اندیس گذاری کردیم، اما در این بخش آن را برحسب colorId نیز اندیس گذاری می‌کنیم.

با توجه به حالت اندیس جاری، روش اندیس گذاری مقادیر آن با استفاده از تابع indexByField خواهد بود. این تابع پاسخگو است، اما اگر سطوح اندیس گذاری زیاد شوند باید از «بازگشت» (Recursion) کمک بگیریم.

1const mapObjectValues = (value, shouldMap, mapFn, ...args) => {
2  if (shouldMap(value)) {
3    return mapFn(value, ...args);
4  }
5  return {
6    ...Object.keys(value).reduce(
7      (acc, k) => ({
8        ...acc,
9        [k]: mapObjectValues(value[k], shouldMap, mapFn, ...args),
10      }),
11      {},
12    ),
13  };
14};
مشاهده کامل کدها

در ادامه این mapObjectValues را به تفصیل توضیح می‌دهیم.

  • Value در نخستین فراخوانی آرایه ما خواهد بود و در فراخوانی بازگشتی بعدی ما اندیس می‌شود.
  • shouldMap تعیین می‌کند چه زمانی فراخوانی‌های بازگشتی را متوقف کنیم. در این مورد این مقدار Array.isArray است.
  • mapFn مقادیر اندیس را تبدیل می‌کند. این فرایند شبیه کاری است که Array.prototype.map روی آیتم‌های آرایه انجام می‌دهد. در این مورد از تابع indexByField استفاده می‌کنیم.

جمع‌بندی

اینک آماده هستیم تابع خود را برای اندیس گذاری یک آرایه برای چند فیلد بنویسیم. ضمناً Array.prototype را طوری بسط می‌دهیم که مستقیماً از وهله ما فراخوانی شود:

1const indexBy = (value, ...fields) => {	
2  if (fields.length === 0) {	
3    return value;	
4  }	
5  const [currentField, ...rest] = fields;	
6  const newValue = mapObjectValues(value, Array.isArray, indexByField, currentField);	
7  return indexBy(newValue, ...rest);	
8};	
9Array.prototype.indexBy = function(...fields) {	
10  return indexBy(this, ...fields);	
11};

اینک کد به صورت زیر درمی‌آید:

1const productColorIndex = skus.indexBy(“productId”, "colorId");

و مقدار آن نیز چنین است:

1{
2  "1": {
3    "1": [
4      {
5        "productId": 1,
6        "colorId": 1,
7        "sku": "11-M"
8      },
9      {
10        "productId": 1,
11        "colorId": 1,
12        "sku": "11-L"
13      }
14    ],
15    "2": [
16      {
17        "productId": 1,
18        "colorId": 2,
19        "sku": "12-M"
20      },
21      {
22        "productId": 1,
23        "colorId": 2,
24        "sku": "12-L"
25      }
26    ]
27  },
28  "2": {
29    "1": [
30      {
31        "productId": 2,
32        "colorId": 1,
33        "sku": "21-M"
34      },
35      {
36        "productId": 2,
37        "colorId": 1,
38        "sku": "21-L"
39      }
40    ]
41  }
42}
مشاهده کامل کدها

اینک می‌توانیم SKU-ها را صرفاً با محاسبه اندیس به دست آوریم:

1productColorIndex["1"]["2"];

سخن پایانی

استفاده از اندیس به جای آرایه می‌تواند در موارد مختلف در اپلیکیشن موجب بهینه‌سازی شود و پیچیدگی را به خصوص در مواردی که لازم است حجم بالایی از داده‌ها مدیریت شوند کاهش دهد. با این حال این مزیت هزینه‌هایی نیز دارد که شامل ایجاد اندیس و نگهداری آن در حافظه می‌شود که در برخی موارد ممکن است کاری پرهزینه باشد.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۱ نفر
آیا این مطلب برای شما مفید بود؟
اگر پرسشی درباره این مطلب دارید، آن را با ما مطرح کنید.
منابع:
itnext
PDF
مطالب مرتبط
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *