2017-01-09 41 views
1

下面的代碼可以工作,但是會在整個數組上進行多次傳遞,這是我想避免的。另一種方法是按名稱對named_coords數組進行排序,然後在遍歷排序後的數組的同時收集pieces,但我沒有找到一個乾淨的方式來完成這項工作。理想情況下,答案將使用標準適配器等來將整個集合進行轉換。將標籤的二維數組轉換爲從標籤到座標的映射的有效方法是什麼?

use std::collections::HashMap; 

fn main() { 
    let p = [ ['I', 'P', 'P', 'Y', 'Y', 'Y', 'Y', 'V', 'V', 'V'] 
      , ['I', 'P', 'P', 'X', 'Y', 'L', 'L', 'L', 'L', 'V'] 
      , ['I', 'P', 'X', 'X', 'X', 'F', 'Z', 'Z', 'L', 'V'] 
      , ['I', 'T', 'W', 'X', 'F', 'F', 'F', 'Z', 'U', 'U'] 
      , ['I', 'T', 'W', 'W', 'N', 'N', 'F', 'Z', 'Z', 'U'] 
      , ['T', 'T', 'T', 'W', 'W', 'N', 'N', 'N', 'U', 'U'] 
      ]; 

    // Gather named coordinates into a Vec 
    let mut named_coords = Vec::new(); 

    for (n0, j0) in p.iter().enumerate() { 
     for (n1, j1) in j0.iter().enumerate() { 
      named_coords.push(((n0, n1), *j1)); 
     } 
    } 

    // Transform the named coordinates into Vector of names. 
    let mut names = named_coords.iter().map(|x| x.1).collect::<Vec<_>>(); 
    names.sort(); 
    names.dedup(); 

    // Filter the named coordinates by name and collect results. 
    // Inefficient - iterates over entire named_coords vector multiple times. 
    let mut pieces = HashMap::new(); 
    for name in names { 
     pieces.insert(name, named_coords.iter().filter(|&p| p.1 == name).map(|p| p.0).collect::<Vec<_>>()); 
    } 

    // Print out results. 
    for n in pieces.iter() { 
     for coord in n.1.iter() { 
      println!("{} {} {}", n.0, coord.0, coord.1); 
     } 
    } 
} 

回答

3

使用entry API:

use std::collections::HashMap; 

fn main() { 
    let p = [['I', 'P', 'P', 'Y', 'Y', 'Y', 'Y', 'V', 'V', 'V'], 
      ['I', 'P', 'P', 'X', 'Y', 'L', 'L', 'L', 'L', 'V'], 
      ['I', 'P', 'X', 'X', 'X', 'F', 'Z', 'Z', 'L', 'V'], 
      ['I', 'T', 'W', 'X', 'F', 'F', 'F', 'Z', 'U', 'U'], 
      ['I', 'T', 'W', 'W', 'N', 'N', 'F', 'Z', 'Z', 'U'], 
      ['T', 'T', 'T', 'W', 'W', 'N', 'N', 'N', 'U', 'U']]; 

    let mut pieces = HashMap::new(); 
    for (n0, j0) in p.iter().enumerate() { 
     for (n1, j1) in j0.iter().enumerate() { 
      pieces.entry(j1).or_insert_with(Vec::new).push((n0, n1)); 
     } 
    } 

    println!("{:?}", pieces); 
} 

高效:單次通過的數據和每件單個散列查找。

簡單:美麗是在旁觀者的眼中。

+1

這是我想出來的。基準測試顯示它速度快1.7倍。 – durka42