This commit is contained in:
sunface 2022-03-28 22:08:01 +08:00
commit 03d010accc
10 changed files with 85 additions and 74 deletions

View File

@ -37,12 +37,12 @@ fn main() {
```rust,editable
fn main() {
let arr: [i32; 5] = [1, 2, 3, 4, 5];
// fill the blanks to make the code work
let slice: __ = __;
assert_eq!(slice, &[2, 3, 4]);
let arr: [i32; 5] = [1, 2, 3, 4, 5];
// fill the blanks to make the code work
let slice: __ = __;
assert_eq!(slice, &[2, 3, 4]);
println!("Success!")
println!("Success!")
}
```

View File

@ -9,9 +9,9 @@ The type of string literal `"hello, world"` is `&str`, e.g `let s: &str = "hello
// fix error without adding new line
fn main() {
let s: str = "hello, world";
let s: str = "hello, world";
println!("Success!")
println!("Success!")
}
```
@ -22,8 +22,8 @@ fn main() {
// fix the error with at least two solutions
fn main() {
let s: Box<str> = "hello, world".into();
greetings(s)
let s: Box<str> = "hello, world".into();
greetings(s)
}
fn greetings(s: &str) {
@ -39,13 +39,13 @@ fn greetings(s: &str) {
// fill the blank
fn main() {
let mut s = __;
s.push_str("hello, world");
s.push('!');
let mut s = __;
s.push_str("hello, world");
s.push('!');
assert_eq!(s, "hello, world!");
assert_eq!(s, "hello, world!");
println!("Success!")
println!("Success!")
}
```
@ -54,7 +54,7 @@ fn main() {
// fix all errors without adding newline
fn main() {
let s = String::from("hello");
let s = String::from("hello");
s.push(',');
s.push(" world");
s += "!".to_string();
@ -68,13 +68,13 @@ fn main() {
// fill the blank
fn main() {
let s = String::from("I like dogs");
// Allocate new memory and store the modified string there
let s1 = s.__("dogs", "cats");
let s = String::from("I like dogs");
// Allocate new memory and store the modified string there
let s1 = s.__("dogs", "cats");
assert_eq!(s1, "I like cats");
assert_eq!(s1, "I like cats");
println!("Success!")
println!("Success!")
}
```
@ -102,25 +102,25 @@ Opsite to the seldom using of `str`, `&str` and `String` are used everywhere!
// fix error with at lest two solutions
fn main() {
let s = "hello, world";
greetings(s)
let s = "hello, world";
greetings(s)
}
fn greetings(s: String) {
println!("{}",s)
}
```
8. 🌟🌟 We can use `String::from` or `to_string` to convert a `&str` to `String`
```rust,editable
// use two approaches to fix the error and without adding a new line
fn main() {
let s = "hello, world".to_string();
let s1: &str = s;
let s = "hello, world".to_string();
let s1: &str = s;
println!("Success!")
println!("Success!")
}
```
@ -256,10 +256,10 @@ You can use [utf8_slice](https://docs.rs/utf8_slice/1.0.0/utf8_slice/fn.slice.ht
```rust
use utf8_slice;
fn main() {
let s = "The 🚀 goes to the 🌑!";
let s = "The 🚀 goes to the 🌑!";
let rocket = utf8_slice::slice(s, 4, 5);
// Will equal "🚀"
let rocket = utf8_slice::slice(s, 4, 5);
// Will equal "🚀"
}
```

View File

@ -18,10 +18,10 @@ fn main() {
// make it works
fn main() {
let t = ("i", "am", "sunface");
assert_eq!(t.1, "sunface");
let t = ("i", "am", "sunface");
assert_eq!(t.1, "sunface");
println!("Success!")
println!("Success!")
}
```
@ -72,13 +72,13 @@ fn main() {
```rust,editable
fn main() {
// fill the blank, need a few computations here.
let (x, y) = sum_multiply(__);
// fill the blank, need a few computations here.
let (x, y) = sum_multiply(__);
assert_eq!(x, 5);
assert_eq!(y, 6);
assert_eq!(x, 5);
assert_eq!(y, 6);
println!("Success!")
println!("Success!")
}
fn sum_multiply(nums: (i32, i32)) -> (i32, i32) {

View File

@ -99,7 +99,8 @@ fn foo() -> i32 {
fn main() {
let pointer = foo as *const ();
let function = unsafe {
std::mem::transmute::<*const (), fn() -> i32>(pointer)
std::mem::transmute::<*const (), fn() -> i32>(pointer)
};
assert_eq!(function(), 0);
}
```

View File

@ -1,12 +1,14 @@
# HashMap
`HashMap` 默认使用 `SipHash 1-3` 哈希算法,该算法对于抵抗 `HashDos` 攻击非常有效。在性能方面,如果你的 key 是中型大小的,那该算法非常不错,但是如果是小型的 key( 例如整数 )亦或是大型的 key ( 例如字符串 ),那你需要采用社区提供的其它算法来提高性能。
哈希表的算法是基于 Google 的 [SwissTable](https://abseil.io/blog/20180927-swisstables),你可以在[这里](https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h)找到 C++ 的实现,同时在 [CppCon talk](https://www.youtube.com/watch?v=ncHmEUmJZf4) 上也有关于算法如何工作的演讲。
### 基本操作
1. 🌟🌟
```rust,editbale
```rust,editable
// 填空并修复错误
use std::collections::HashMap;
@ -37,6 +39,7 @@ fn main() {
```
2. 🌟🌟
```rust,editable
use std::collections::HashMap;
@ -63,6 +66,7 @@ fn main() {
```
3. 🌟🌟
```rust,editable
// 填空
@ -95,18 +99,19 @@ fn random_stat_buff() -> u8 {
```
### HashMap key 的限制
任何实现了 `Eq``Hash` 特征的类型都可以用于 `HashMap` 的 key包括:
- `bool` (虽然很少用到,因为它只能表达两种 key)
- `int`, `uint` 以及它们的变体,例如 `u8`、`i32` 等
- `String``&str` (提示: `HashMap` 的 key 是 `String` 类型时,你其实可以使用 `&str` 配合 `get` 方法进行查询
需要注意的是,`f32` 和 `f64` 并没有实现 `Hash`,原因是 [浮点数精度](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems) 的问题会导致它们无法进行相等比较。
如果一个集合类型的所有字段都实现了 `Eq``Hash`,那该集合类型会自动实现 `Eq``Hash`。例如 `Vect<T>` 要实现 `Hash`,那么首先需要 `T` 实现 `Hash`
4. 🌟🌟
```rust,editable
// 修复错误
@ -143,9 +148,11 @@ fn main() {
```
### 容量
关于容量,我们在之前的 [Vector](https://zh.practice.rs/collections/vector.html#容量) 中有详细的介绍,而 `HashMap` 也可以调整容量: 你可以通过 `HashMap::with_capacity(uint)` 使用指定的容量来初始化,或者使用 `HashMap::new()` ,后者会提供一个默认的初始化容量。
#### 示例
```rust,editable
use std::collections::HashMap;
@ -169,10 +176,11 @@ fn main() {
```
### 所有权
对于实现了 `Copy` 特征的类型,例如 `i32`,那类型的值会被拷贝到 `HashMap` 中。而对于有所有权的类型,例如 `String`,它们的值的所有权将被转移到 `HashMap` 中。
5. 🌟🌟
```rust,editable
// 修复错误,尽可能少的去修改代码
// 不要移除任何代码行!
@ -187,7 +195,7 @@ fn main() {
let mut m2 = HashMap::new();
// 所有权在这里发生了转移
m2.insert(v2, v1);
assert_eq!(v2, "hello");
println!("Success!")
@ -195,6 +203,7 @@ fn main() {
```
### 三方库 Hash 库
在开头,我们提到过如果现有的 `SipHash 1-3` 的性能无法满足你的需求,那么可以使用社区提供的替代算法。
例如其中一个社区库的使用方式如下:
@ -211,4 +220,4 @@ hash.insert(42, "the answer");
assert_eq!(hash.get(&42), Some(&"the answer"));
```
> You can find the solutions [here](https://github.com/sunface/rust-by-practice)(under the solutions path), but only use it when you need it
> You can find the solutions [here](https://github.com/sunface/rust-by-practice)(under the solutions path), but only use it when you need it

View File

@ -35,7 +35,7 @@ fn main() {
```rust,editable
fn main() {
let arr: [i32; 5] = [1, 2, 3, 4, 5];
let arr: [i32; 5] = [1, 2, 3, 4, 5];
// 填空让代码工作起来
let slice: __ = __;
assert_eq!(slice, &[2, 3, 4]);

View File

@ -9,7 +9,7 @@
// 修复错误,不要新增代码行
fn main() {
let s: str = "hello, world";
let s: str = "hello, world";
}
```
@ -20,8 +20,8 @@ fn main() {
// 使用至少两种方法来修复错误
fn main() {
let s: Box<str> = "hello, world".into();
greetings(s)
let s: Box<str> = "hello, world".into();
greetings(s)
}
fn greetings(s: &str) {
@ -37,11 +37,11 @@ fn greetings(s: &str) {
// 填空
fn main() {
let mut s = __;
s.push_str("hello, world");
s.push('!');
let mut s = __;
s.push_str("hello, world");
s.push('!');
assert_eq!(s, "hello, world!");
assert_eq!(s, "hello, world!");
}
```
@ -50,7 +50,7 @@ fn main() {
// 修复所有错误,并且不要新增代码行
fn main() {
let s = String::from("hello");
let s = String::from("hello");
s.push(',');
s.push(" world");
s += "!".to_string();
@ -64,11 +64,11 @@ fn main() {
// 填空
fn main() {
let s = String::from("I like dogs");
// 以下方法会重新分配一块内存空间,然后将修改后的字符串存在这里
let s1 = s.__("dogs", "cats");
let s = String::from("I like dogs");
// 以下方法会重新分配一块内存空间,然后将修改后的字符串存在这里
let s1 = s.__("dogs", "cats");
assert_eq!(s1, "I like cats")
assert_eq!(s1, "I like cats")
}
```
@ -98,23 +98,23 @@ fn main() {
// 使用至少两种方法来修复错误
fn main() {
let s = "hello, world";
greetings(s)
let s = "hello, world";
greetings(s)
}
fn greetings(s: String) {
println!("{}",s)
}
```
8. 🌟🌟 我们可以使用 `String::from``to_string``&str` 转换成 `String` 类型
```rust,editable
// 使用两种方法来解决错误,不要新增代码行
fn main() {
let s = "hello, world".to_string();
let s1: &str = s;
let s = "hello, world".to_string();
let s1: &str = s;
}
```
@ -135,7 +135,7 @@ fn main() {
unicode_codepoint, character_name );
// 还能使用 \ 来连接多行字符串
let long_string = "String literals
let long_string = "String literals
can span multiple lines.
The linebreak and indentation here \
can be escaped too!";
@ -247,10 +247,10 @@ fn main() {
```rust
use utf8_slice;
fn main() {
let s = "The 🚀 goes to the 🌑!";
let s = "The 🚀 goes to the 🌑!";
let rocket = utf8_slice::slice(s, 4, 5);
// 结果是 "🚀"
let rocket = utf8_slice::slice(s, 4, 5);
// 结果是 "🚀"
}
```

View File

@ -16,8 +16,8 @@ fn main() {
// 修改合适的地方,让代码工作
fn main() {
let t = ("i", "am", "sunface");
assert_eq!(t.1, "sunface");
let t = ("i", "am", "sunface");
assert_eq!(t.1, "sunface");
}
```
@ -64,11 +64,11 @@ fn main() {
```rust,editable
fn main() {
// 填空,需要稍微计算下
let (x, y) = sum_multiply(__);
// 填空,需要稍微计算下
let (x, y) = sum_multiply(__);
assert_eq!(x, 5);
assert_eq!(y, 6);
assert_eq!(x, 5);
assert_eq!(y, 6);
}
fn sum_multiply(nums: (i32, i32)) -> (i32, i32) {

View File

@ -100,7 +100,8 @@ fn foo() -> i32 {
fn main() {
let pointer = foo as *const ();
let function = unsafe {
std::mem::transmute::<*const (), fn() -> i32>(pointer)
std::mem::transmute::<*const (), fn() -> i32>(pointer)
};
assert_eq!(function(), 0);
}
```

View File

@ -143,4 +143,4 @@ fn main() {
}
```
> 你可以在[这里](https://github.com/sunface/rust-by-practice)找到答案(在 solutions 路径下)
> [答案](https://github.com/sunface/rust-by-practice/blob/master/solutions/variables.md) 在 solutions 下面