简体   繁体   English

如何比较 HashMap 中的向量键?

[英]How to compare keys of vector in a HashMap?

I have a scenario where I have to compare the keys of vector.我有一个场景,我必须比较向量的键。 I have 2 values in each vector key.我在每个向量键中有 2 个值。

I have to find a vector key in which我必须找到一个向量键,其中

  1. first value of the vector should be greater than all first value of each vector key向量的第一个值应该大于每个向量键的所有第一个值
  2. and the second value of the vector should be smaller than all second value of each vector key并且向量的第二个值应该小于每个向量键的所有第二个值

Please find below sample code:请在下面找到示例代码:

let mut queue : HashMap<Vec<u8>, Vec<u8>> = HashMap::new();

queue.insert(vec![5 as u8, queue.keys().len() as u8], vec![0]);
queue.insert(vec![10 as u8, queue.keys().len() as u8], vec![1]);
queue.insert(vec![10 as u8, queue.keys().len() as u8], vec![2]);
queue.insert(vec![3 as u8, queue.keys().len() as u8], vec![2]);
queue.insert(vec![4 as u8, queue.keys().len() as u8], vec![3]);
queue.insert(vec![6 as u8, queue.keys().len() as u8], vec![4]);

let key= queue
    .iter()
    .max_by(|a, b| {
        a.0.cmp(&b.0)
    })
    .map(|(k, _v)| k);

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

I am getting this output Some([10, 2]) .我得到这个 output Some([10, 2]) But I want Some([10, 1]) as output.但我想要Some([10, 1])作为 output。 ` `

here is my map: {[10, 1]: [1], [4, 4]: [3], [6, 5]: [4], [10, 2]: [2], [3, 3]: [2], [5, 0]: [0]}这是我的 map: {[10, 1]: [1], [4, 4]: [3], [6, 5]: [4], [10, 2]: [2], [3, 3]: [2], [5, 0]: [0]}

You want a max_by comparison function which compares the first element to find which is greatest and the second to find which is smallest.你想要一个max_by比较 function 比较第一个元素以找到最大的元素,第二个元素找到最小的元素。 Let's deal with the first criterion first: the first element should be largest.让我们先处理第一个标准:第一个元素应该是最大的。

a.0[0].cmp(&b.0[0])

a.0 and b.0 , as you've likely already surmised, select the key from the key-value pair provided. a.0b.0 ,正如您可能已经推测的那样, select 是提供的键值对中的键。 Then we use ordinary [] indexing to get the first element of the vector.然后我们使用普通的[]索引来获取向量的第一个元素。

Now, I'm assuming for the purposes of the question that we want lexicographic ordering , also called dictionary order.现在,出于这个问题的目的,我假设我们想要字典顺序,也称为字典顺序。 That is, you've listed two criteria, and I'm assuming the first takes precedent, so that for instance [10, 2] should be favorable to [9, 1] , since the first element is bigger, despite the fact that the second is not smaller.也就是说,您已经列出了两个标准,我假设第一个是先例,因此例如[10, 2]应该有利于[9, 1] ,因为第一个元素更大,尽管事实上第二个不小。

With that assumption in mind, we can expand our comparison.考虑到这个假设,我们可以扩大我们的比较。 To reverse an ordering (ie to select a smallest rather than largest element) we can simply switch the order of arguments.要反转排序(即 select 是最小的而不是最大的元素),我们可以简单地切换 arguments 的顺序。

b.0[1].cmp(&a.0[1])

Then we only want to use this comparison if the first failed us, ie if the first was equal.然后我们只想在第一个失败的情况下使用这个比较,即如果第一个相等。

match a.0[0].cmp(&b.0[0]) {
  Ordering::Equal => b.0[1].cmp(&a.0[1]),
  x => x
}

If we put this in your max_by function, we get [10, 1] , as desired.如果我们把它放在你的max_by function 中,我们会根据需要得到[10, 1]

But we can actually do one better.但我们实际上可以做得更好。 See, lexicographic ordering is fairly common, so common that it's built-in to Rust.看,字典顺序相当普遍,以至于它内置在 Rust 中。 We can use the method Ordering::then as follows.我们可以使用Ordering::then方法,如下所示。

a.0[0].cmp(&b.0[0]).then(b.0[1].cmp(&a.0[1]))

And this works identically to the previous example.这与前面的示例相同。

Complete example:完整示例:

let mut queue : HashMap<Vec<u8>, Vec<u8>> = HashMap::new();

queue.insert(vec![5 as u8, queue.keys().len() as u8], vec![0]);
queue.insert(vec![10 as u8, queue.keys().len() as u8], vec![1]);
queue.insert(vec![10 as u8, queue.keys().len() as u8], vec![2]);
queue.insert(vec![3 as u8, queue.keys().len() as u8], vec![2]);
queue.insert(vec![4 as u8, queue.keys().len() as u8], vec![3]);
queue.insert(vec![6 as u8, queue.keys().len() as u8], vec![4]);

let key = queue
  .iter()
  .max_by(|a, b| {
    a.0[0].cmp(&b.0[0]).then(b.0[1].cmp(&a.0[1]))
  })
  .map(|(k, _v)| k);

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

HashMap is the wrong data structure for this task. HashMap 是此任务的错误数据结构。 In order to solve this problem, you have to access every element of the map.为了解决这个问题,您必须访问 map 的每个元素。 If you have control over your data, you should store it in a BTreeMap instead.如果您可以控制数据,则应将其存储在 BTreeMap 中。 Then the solution to your problem becomes:那么你的问题的解决方案就变成了:

fn get_first_of_max(queue: &BTreeMap<Vec<u8>, Vec<u8>>) -> Option<Vec<u8>> {
    let max_key_prefix = queue.keys().rev().next()?;
    queue.range((
        Bound::Included(vec![max_key_prefix[0], 0]), 
        Bound::Unbounded,
    )).next().map(|x| x.0.to_owned())
}

Given what you're doing with your values, I'd also prefer a (u8, usize) for the key.鉴于您对自己的价值观所做的事情,我也更喜欢(u8, usize)作为密钥。 Combined with the above, you get:结合以上,你得到:

use std::collections::BTreeMap;
use std::ops::Bound;

fn get_first_of_max(queue: &BTreeMap<(u8, usize), Vec<u8>>) -> Option<(u8, usize)> {
    let max_key_prefix = queue.keys().rev().next()?;
    queue.range((
        Bound::Included((max_key_prefix.0, 0)), 
        Bound::Unbounded,
    )).next().map(|x| x.0.to_owned())
}

fn main() {
    let mut queue = BTreeMap::new();

    queue.insert((5, queue.keys().len()), vec![0]);
    queue.insert((10, queue.keys().len()), vec![1]);
    queue.insert((10, queue.keys().len()), vec![2]);
    queue.insert((3, queue.keys().len()), vec![3]);
    queue.insert((4, queue.keys().len()), vec![4]);
    queue.insert((6, queue.keys().len()), vec![5]);

    println!("{:?}", get_first_of_max(&queue));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM