কীভাবে হ্যাশম্যাপ থেকে সন্ধান এবং কার্যকরভাবে ?োকানো যায়?


102

আমি নিম্নলিখিত করতে চাই:

  • একটি লুকআপ Vecএকটি নির্দিষ্ট কী-এর জন্য, এবং পরে ব্যবহারের জন্য এটি সংরক্ষণ করি।
  • যদি এটি বিদ্যমান না থাকে Vecতবে কীটির জন্য একটি খালি তৈরি করুন , তবে এখনও এটি ভেরিয়েবলের মধ্যে রাখুন।

কীভাবে এটি দক্ষতার সাথে করবেন? স্বাভাবিকভাবেই আমি ভেবেছিলাম আমি ব্যবহার করতে পারি match:

use std::collections::HashMap;

// This code doesn't compile.
let mut map = HashMap::new();
let key = "foo";
let values: &Vec<isize> = match map.get(key) {
    Some(v) => v,
    None => {
        let default: Vec<isize> = Vec::new();
        map.insert(key, default);
        &default
    }
};

আমি যখন এটি চেষ্টা করেছিলাম তখন এটি আমাকে ত্রুটি দেয়:

error[E0502]: cannot borrow `map` as mutable because it is also borrowed as immutable
  --> src/main.rs:11:13
   |
7  |     let values: &Vec<isize> = match map.get(key) {
   |                                     --- immutable borrow occurs here
...
11 |             map.insert(key, default);
   |             ^^^ mutable borrow occurs here
...
15 | }
   | - immutable borrow ends here

আমি এই জাতীয় কিছু করে শেষ করেছিলাম, তবে আমি এটি পছন্দ করি না যে এটি দু'বার ( map.contains_keyএবং map.get) অনুসন্ধান করে:

// This code does compile.
let mut map = HashMap::new();
let key = "foo";
if !map.contains_key(key) {
    let default: Vec<isize> = Vec::new();
    map.insert(key, default);
}
let values: &Vec<isize> = match map.get(key) {
    Some(v) => v,
    None => {
        panic!("impossiburu!");
    }
};

এটির একটি নিরাপদ উপায় কি কেবল একটি দিয়ে match?

উত্তর:


119

entryএপিআই এই জন্য নির্মিত হয়েছে। ম্যানুয়াল আকারে, এটি দেখতে দেখতে হতে পারে

use std::collections::hash_map::Entry;

let values: &Vec<isize> = match map.entry(key) {
    Entry::Occupied(o) => o.into_mut(),
    Entry::Vacant(v) => v.insert(default)
};

অথবা কেউ ব্রাইফার ফর্মটি ব্যবহার করতে পারেন:

map.entry(key).or_insert_with(|| default)

তাহলে defaultঠিক আছে / সস্তা এমনকি যখন এটা সন্নিবেশিত করা হয় না গনা হয়, এটি শুধু হতে পারে:

map.entry(key).or_insert(default)

একটি দ্রুত অগ্রসর জন্য ধন্যবাদ! এখন আমি শিখেছি আমার ডকুমেন্টগুলির আরও গভীর দিকে নজর দেওয়া উচিত।
ইউসুখে শিনিয়ামা

22
এন্ট্রি () সহ সমস্যাটি হ'ল, আপনাকে সর্বদা কীটি ক্লোন করতে হবে, এড়াতে কি কোনও উপায় আছে?
পাস্কালিয়াস

@ প্যাসালিয়াস আপনি আপনার মূল প্রকারটি তৈরি করতে &Tপারেন (যদি কীগুলি মানচিত্রকে ছাড়িয়ে রাখে , যেমন স্ট্যাটিক স্ট্রিংগুলি) বা এর Rc<T>পরিবর্তে T- তবে এটি কোনও ক্ষেত্রেই সুন্দর নয়
kbolino

@ প্যাসালিয়াস: আপনি v.key()এই অভিব্যক্তিটি ব্যবহার করতে পারেন defaultএবং তারপরে এটি হ্যাশম্যাপে বিদ্যমান বলে কীটির একটি রেফারেন্স পাবেন, সুতরাং আপনি এইভাবে একটি ক্লোন এড়াতে পারেন
ক্রিস বেক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.