Hash 如何将输入映射到具有相同输出和均匀分布保证的输出?
我有一组大小可变的输入(在我的例子中是字符串),需要映射到一组大小固定的输出(在我的例子中是数组的索引)。因此,我基本上需要一个函数,如:Hash 如何将输入映射到具有相同输出和均匀分布保证的输出?,hash,rust,mapping,distribution,uniform-distribution,Hash,Rust,Mapping,Distribution,Uniform Distribution,我有一组大小可变的输入(在我的例子中是字符串),需要映射到一组大小固定的输出(在我的例子中是数组的索引)。因此,我基本上需要一个函数,如: fn map(input: String) -> usize; 我需要保证两件事: 对于任何输入X我必须始终返回相同的输出Y。例如:每次我将字符串“hello”传递给我的函数时,返回的值必须始终相同,例如1 返回值的分布必须一致,即对于无限多的输入,相同返回值的平均值必须相同。例如,如果我有M=4不同的返回值,并且我有N=100不同的输入,则映射到每
fn map(input: String) -> usize;
我需要保证两件事:
X
我必须始终返回相同的输出Y
。例如:每次我将字符串“hello”
传递给我的函数时,返回的值必须始终相同,例如1
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]
}
}
使用std::collections::hash\u map::DefaultHasher;
使用std::hash::{hash,Hasher};
fn main(){
让bucket=bucket::new(5);
让输入=[“你好”、“世界”、“房子”、“你好”];
用于输入(&I){
让输出=bucket.get(输入);
assert_eq!(输出,bucket.get(输入));
println!(“{}->{}”,输入,输出);
}
}
pub结构桶{
价值观:Vec,
}
impl铲斗{
pub fn new(尺寸:usize)->Self{
让值=(0..size).collect();
Bucket{values}
}
pub fn get(&self,id:&T)->usize{
让mut hasher=DefaultHasher::new();
散列::散列(id,&mut散列器);
让index=(hasher.finish()%self.values.len()作为u64)作为usize;
自我价值[索引]
}
}
我认为上面的代码保证了第一点(对于相同的输入总是相同的输出),但不一定保证第二点(分布的均匀性)
这样一个函数是否有一个快速的实现,以保证这两个点?我想你是正确的,第一点与你的实现是一致的 关于第二点:这取决于
DefaultHasher
的功能。在实践中,这可能已经足够好了,但还有另一种技术可以满足您的需求:
- 有一个计数器
,最初为0m
- 将
映射到HashMap
usize
- 每当您想
获取结果时,请在
中查找给定的字符串:HashMap
- 如果字符串已存在,则返回关联的值
- 如果该字符串尚未出现:
- 将新条目添加到将给定字符串映射到当前值
的m
HashMap
- 将
增加1m
- 如果
,则将m重置为0m==m
Bucket::get
操作变成一个可变操作,使用&mut self
来增加这个计数器,在多线程上下文中,这个计数器需要一个带互斥锁的写锁,这将大大降低impl的速度。输入/输出是作为一个整体给出的吗?如果是这样的话,您可以将所有这些作为预处理来完成(在预处理中,易变性不应该是太大的问题)。只有在启动时作为一个整体提供输出(固定),而输入不是,每个新请求都可以提供一个新的输入。