什么是将二维标签数组转换为从标签到坐标的地图的有效方法?

时间:2017-01-09 21:52:53

标签: arrays iterator rust

以下代码可以正常工作,但会对整个数组进行多次传递,我希望避免这种情况。另一个替代方法是按名称对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);
        }
    }
}

1 个答案:

答案 0 :(得分: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);
}

高效:单个传递数据和每个项目的单个哈希查找。

简单:美丽在旁观者的眼中。