【问题标题】:How to map inputs to outputs with same output and uniform distribution guarantees?如何将输入映射到具有相同输出和均匀分布保证的输出?
【发布时间】:2019-11-28 04:53:52
【问题描述】:

我有一组可变大小 N 的输入(在我的情况下为 Strings),我需要映射到一组固定大小的输出(在我的情况下为数组的索引)M .所以,我基本上需要这样的功能:

fn map(input: String) -> usize;

我需要保证两件事:

  1. 对于任何输入X,我必须始终返回相同的输出Y。例如:每次我将字符串 "hello" 传递给我的函数时,返回的值必须始终相同,例如 1
  2. 返回值的分布必须是均匀的,也就是说,对于无数个输入,相同返回值的平均值必须相同。例如,如果我有 M = 4 不同的值要返回,并且我有 N = 100 不同的输入,则映射到每个输出的输入数量在理想情况下必须等于 25

我想出了以下代码:

use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

fn main() {
    let bucket = Bucket::new(5);
    let inputs = ["hello", "world", "house", "hi"];

    for input in &inputs {
        let output = bucket.get(input);
        assert_eq!(output, bucket.get(input));
        println!("{} -> {}", input, output);
    }
}

pub struct Bucket {
    values: Vec<usize>,
}

impl Bucket {
    pub fn new(size: usize) -> Self {
        let values = (0..size).collect();
        Bucket { values }
    }

    pub fn get<T: Hash>(&self, id: &T) -> usize {
        let mut hasher = DefaultHasher::new();
        Hash::hash(id, &mut hasher);
        let index = (hasher.finish() % self.values.len() as u64) as usize;
        self.values[index]
    }
}

Link to Playground

我认为上面的代码保证了第一点(对于相同的输入总是相同的输出),但不一定是第二点(分布的均匀性)。

有没有快速实现这样的功能,从而保证两点?

【问题讨论】:

    标签: hash rust mapping distribution uniform-distribution


    【解决方案1】:

    我认为你的第一点是正确的,你的实现是正确的。

    关于第二点:这取决于DefaultHasher 做了什么。在实践中它可能已经足够好了,但是还有另一种技术可以满足您的要求:

    • 有一个计数器 m,最初为 0。
    • 有一个HashMap 映射Stringusize
    • 无论何时你想要get 的结果,在HashMap 中查找给定的字符串:
      • 如果字符串已经存在,则返回相关值。
      • 如果字符串不存在:
      • HashMap 添加一个新条目,将给定字符串映射到m 的当前值。
      • m 增加 1。
      • 如果m==M,将m重置为0。

    【讨论】:

    • 这需要 O(N) 内存
    • 如果我没记错的话,这种方法的问题是我需要将Bucket::get 操作设为可变操作,采用&amp;mut self 以增加此计数器,其中多线程上下文需要一个带有互斥锁的写锁,这会大大减慢 impl。
    • @gliderkite 输入/输出是否作为一个整体给出?如果是这样,您可以将所有这些作为预处理来完成(可变性应该不是那么大的问题)。
    • 在启动时只给出一个整体的输出(固定),而输入不是,每个新请求都可以呈现一个新的输入。
    猜你喜欢
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-12
    • 1970-01-01
    • 2022-01-20
    相关资源
    最近更新 更多