2015-06-30 20 views
7

Bir HashMap varsayalım ve bir girdiye değiştirilebilen bir başvuru almak istiyorum veya bu girdi yoksa yeni bir nesneye değiştirilebilir bir başvuru istiyorum, bunu nasıl yapabilirim?Varsayılan değiştirilebilen değer: HashMap

fn foo() { 
    let mut map: HashMap<&str, Vec<&str>> = HashMap::new(); 

    let mut ref = map.get_mut("whatever").unwrap_or(&mut Vec::<&str>::new()); 

    // Modify ref. 
} 

Ama Vec yaşam boyu yeterince uzun olmadığı için bu işe yaramazsa: Böyle unwrap_or(), bir şey kullanarak denedim. Vec'un foo() ile aynı ömre sahip olmasını istediğimi Rust'a söylemenin bir yolu var mı? Bu bariz bir çözüm yoktur demek ama daha iyi bir yolu olması gerektiğini hissediyorum:

fn foo() { 
    let mut map: HashMap<&str, Vec<&str>> = HashMap::new(); 

    let mut dummy: Vec<&str> = Vec::new(); 
    let mut ref = map.get_mut("whatever").unwrap_or(&dummy); 

    // Modify ref. 
} 
+5

Herhangi bir noktada haritaya 'dummy 'eklemeden bunu yapmak ister misiniz? Sadece merak ediyorum. – bluss

+0

Tam olarak, benim özel kullanım durumumda sadece bir tercih olmasına rağmen. Yine de, 'dummy' eklemek istemeyeceğiniz durumlar hayal edebiliyorum. – Timmmm

cevap

10

, burada girişi kullanarak bir örnektir Desen. İlk başta ayrıntılı görünüyor, ancak bu ihtiyacınız olmadıkça kullanamayacağınız bir dizi ayırmayı önler. Bunu çevresinde genel fonksiyon gevezeliği azaltmak için yapabilir eminim :)

Sadece keşfedilen gibi bu da or_insert için kısaltılabilir
use std::collections::HashMap; 
use std::collections::hash_map::Entry::{Occupied, Vacant}; 

fn foo() { 
    let mut map = HashMap::<&str, Vec<&str>>::new(); 
    let mut result = match map.entry("whatever") { 
     Vacant(entry) => entry.insert(Vec::new()), 
     Occupied(entry) => entry.into_mut(), 
    }; 

    // Do the work 
    result.push("One thing"); 
    result.push("Then another"); 
} 

!

use std::collections::HashMap; 

fn foo() { 
    let mut map = HashMap::<&str, Vec<&str>>::new(); 
    let mut result = map.entry("whatever").or_insert(Vec::new()); 

    // Do the work 
    result.push("One thing"); 
    result.push("Then another"); 
} 
+3

['or_insert'] kullanımı (http://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.or_insert) daha kısa versiyonudur ([Örnek] (http: // is .gd/GQYapJ)). – Shepmaster

6

haritadan içine dummy eklemek istiyorsanız, o zaman bu How to properly use HashMap::entry? veya Want to add to HashMap using pattern match, get borrow mutable more than once at a time kopyasıdır (veya herhangi bir soru hakkında entry API).

Eklemek istemezseniz, kodunuz düzgün, düzeltmek için derleyici hata iletilerini izlemeniz yeterlidir. Bir tanımlayıcı (ref) gibi bir anahtar kelime kullanmaya çalıştığınız ve dummy bir değişken başvuru (& mut dummy) almak gerekir: Shepmaster tarafından belirtildiği gibi

use std::collections::HashMap; 

fn foo() { 
    let mut map: HashMap<&str, Vec<&str>> = HashMap::new(); 

    let mut dummy: Vec<&str> = Vec::new(); 
    let f = map.get_mut("whatever").unwrap_or(&mut dummy); 
} 

fn main() {}