Ha

HashMap در Rust

{one: "۱ تمرین", other: "%{count} تمرین"}

درباره‌ی HashMap

یک HashMap ظرفی است که می‌توان از آن برای ذخیره‌ی جفت‌های کلید-مقدار استفاده کرد. در زبان‌های برنامه‌نویسی دیگر، به این ساختار داده گاهی آرایه‌ی انجمنی یا جدول هش می‌گویند. این نقشه مجموعه‌ای از کلیدها را در خود دارد که هرکدام به مقدار مشخصی نگاشت شده‌اند. کاربر می‌تواند با دادن کلید مناسب، مقدار ذخیره‌شده را بازیابی کند. کاربران همچنین می‌توانند کلیدها و مقادیر مرتبط با آن‌ها را درج و حذف کنند.

HashMap یک مجموعه‌ی جنریک است (مانند بیشتر مجموعه‌های کتابخانه‌ی استاندارد) و بنابراین از انواع گوناگونی به‌عنوان کلید پشتیبانی می‌کند، از جمله ساختارهای تعریف‌شده توسط کاربر و تاپل‌ها. مقادیر آن می‌توانند از هر نوعی باشند.

ساخت یک HashMap

یک HashMap با استفاده از تابع HashMap::new() ساخته می‌شود. قطعه‌کد زیر یک HashMap می‌سازد که در آن اسم تیم‌ها به امتیازها نگاشت شده‌اند.

use std::collections::HashMap;

let mut scores = HashMap::new();

scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

دسترسی به مقادیر در HashMap

اگر بدانیم مقداری در HashMap وجود دارد، استفاده از عملگر نمایه‌سازی ([]) مناسب است. برای نمونه، برای بازیابی امتیاز تیم آبی می‌توانیم از scores["Blue"] استفاده کنیم. اما اگر جفت کلید-مقدار مناسب درون این هش‌مپ وجود نداشته باشد، این عملیات panic می‌کند.

جز عملگر نمایه‌سازی، دو راه دیگر هم برای دسترسی به مقادیر ذخیره‌شده در یک HashMap وجود دارد. راه اول استفاده از تابع عضو get است:

if let Some(blue_score) = scores.get("Blue") {
    println!("Blue scored: {blue_score} \n");
}

get به مقداری که در برابر کلید درخواستی ذخیره شده دسترسی پیدا می‌کند. اگر کلید داده‌شده در HashMap وجود نداشته باشد None را برمی‌گرداند، و اگر کلید وجود داشته باشد Some(value) را برمی‌گرداند. برای اطلاعات بیشتر درباره‌ی Options در Rust، مفهوم Options را ببینید.

راه دیگر برای دسترسی به مقادیر ذخیره‌شده در یک HashMap استفاده از متد entry است. متد entry (یا entry API) ارجاعی به ورودی جفت کلید-مقدار در HashMap برمی‌گرداند. این ورودی وضعیت این کلید را در هش نشان می‌دهد. اگر کلید وجود نداشته باشد، مقداری در ورودی نیست (و اجازه می‌دهد یکی درج شود).

let mut vote_counter: HashMap<_, usize> = HashMap::new();
let votes = ["Blue", "Red", "Red", "Blue", "Red", "Blue", "Blue"];
for vote in votes {
    let count = vote_counter.entry(vote).or_default();
    *count += 1;
}

println!("{vote_counter:#?}");

این API برخی الگوهای دسترسی رایج را بسیار راحت می‌کند؛ مفهوم کاملی (Entry API) به آن اختصاص یافته است.

کارایی

HashMapها نسبتاً سریع‌اند و برای همه‌ی عملیات‌هایی که با یک کلید سر و کار دارند، پیچیدگی زمانی ثابت سرشکن‌شده (O(1)) دارند.

محدودیت‌های trait

HashMap یک ساختار داده‌ی جنریک است، یعنی از انواع دلخواه برای استفاده به‌عنوان کلید و مقدار پشتیبانی می‌کند، با تنها یک قید: برای اینکه یک نوع به‌عنوان نوع کلید به کار رود، باید پیاده‌سازی‌ای برای دو trait داشته باشد: Eq و Hash. روی نوع مقدار هیچ محدودیت traitی وجود ندارد.

ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود