gpt4 book ai didi

iterator - 一般遍历映射或二元组向量

转载 作者:行者123 更新时间:2023-11-29 07:56:41 26 4
gpt4 key购买 nike

因为reasons ,我想定义一个通用函数,它可以迭代表示为映射或二元组向量的键值对(或满足 IntoIterator<Item=(K, V)> 的任何其他内容,其中 KV 是字符串的).具体来说,我希望它能工作:

use std::collections::HashMap;

fn main() {
let vc = vec![
("a", "foo"),
("b", "bar"),
("c", "baz")
];
operate(&vc);

let mut map = HashMap::new();
map.insert("d", "blurf");
map.insert("e", "quux");
map.insert("f", "xyzzy");
operate(&map);
}

我有一个 operate 的定义适用于 HashMap,但不适用于向量:

fn operate<I, K, V>(x: I)
where I: IntoIterator<Item=(K, V)>,
K: AsRef<str>, V: AsRef<str>
{
for (ref k, ref v) in x {
println!("{}: {}", k.as_ref(), v.as_ref());
}
}

我得到的错误信息是

error[E0271]: type mismatch resolving `<&std::vec::Vec<(&str, &str)> as std::iter::IntoIterator>::Item == (_, _)`
--> test.rs:18:5
|
18 | operate(&vc);
| ^^^^^^^ expected reference, found tuple
|
= note: expected type `&(&str, &str)`
= note: found type `(_, _)`
= note: required by `operate`

我完全不明白。一方面,它似乎是倒退的,另一方面,为什么我只收到 Vec 的错误?而不是 HashMap

最佳答案

IntoIterator 提供的功能消耗 self 。

fn into_iter(self) -> Self::IntoIter

为了允许使用 IntoIterator在不消耗集合的情况下, Vec HashMap IntoIterator 的实现对于 &'a Vec<T>&'a HashMap<K,V,S> , 分别。然而,它们并不完全相同。

对于 HashMap ,每个Item(&K, &V) ,这不会造成问题,因为代码有效地将项目假定为强制为 &str 的键和值的 2 大小元组。 .和 &&str确实强制&str .对于向量,每个 Item&T (因此在本例中为 &(K, V)),但因为函数期望 (K, V)作为迭代项,目前无法处理&(K, V)的项.

实际上,如果您移动向量,该函数就会工作,这会产生一个 IntoIterator其中 Item = (K, V) :

let vc = vec![
("a", "foo"),
("b", "bar"),
("c", "baz")
];
operate(vc);

但是如果我们希望它对两个集合都有效而不消耗它们中的任何一个怎么办?好吧,我刚刚设计了两个解决方案。

#1

这涉及将元组隐藏在新特征后面:

/// for stuff that can be turned into a pair of references
trait AsRefPair<K, V> {
fn as_ref_pair(&self) -> (&K, &V);
}

&(K,V) 实现它和 (&K,&V) :

impl<'a, K, V> AsRefPair<K, V> for (&'a K, &'a V) {
fn as_ref_pair(&self) -> (&K, &V) {
(self.0, self.1)
}
}

impl<'a, K, V> AsRefPair<K, V> for &'a (K, V) {
fn as_ref_pair(&self) -> (&K, &V) {
(&self.0, &self.1)
}
}

现在这个函数起作用了:

fn operate<I, T, K, V>(x: I)
where I: IntoIterator<Item=T>,
T: AsRefPair<K, V>,
K: AsRef<str>, V: AsRef<str>
{
for p in x {
let (ref k, ref v) = p.as_ref_pair();
println!("{}: {}", k.as_ref(), v.as_ref());
}
}

Playground .起初听起来有点疯狂,但是......!

#2

在这一个中,停止使用元组...并开始使用键值!

trait KeyValue<K, V> {
fn key_value(&self) -> (&K, &V) {
(self.key(), self.value())
}

fn key(&self) -> &K;
fn value(&self) -> &V;
}

impl<K, V> KeyValue<K, V> for (K, V) {
fn key(&self) -> &K {
&self.0
}
fn value(&self) -> &V {
&self.1
}
}

impl<'a, K, V> KeyValue<K, V> for &'a (K, V) {
fn key(&self) -> &K {
&self.0
}
fn value(&self) -> &V {
&self.1
}
}

fn operate<I, T, K, V>(x: I)
where I: IntoIterator<Item=T>,
T: KeyValue<K, V>,
K: AsRef<str>, V: AsRef<str>
{
for p in x {
let (ref k, ref v) = p.key_value();
println!("{}: {}", k.as_ref(), v.as_ref());
}
}

Playground .我觉得这个更符合习惯。

关于iterator - 一般遍历映射或二元组向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41626209/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com