使用 Itertools 按字符串中出现的次数对字符进行分组

问题描述 投票:0回答:3

我有两种方法根据字符串中出现的次数对字符进行分组。其中之一是使用

std::collections::HashMap
,第二个是使用
itertools::Itertools::group_by
。不幸的是,与
Itertools
分组给了我不想要的结果。

输入单词示例:

"Barbara"

使用

std::collections::HashMap

let map1 = word.to_lowercase()
    .chars()
    .fold(HashMap::new(), |mut acc, c| {
        *acc.entry(c).or_insert(0) += 1;
        acc
    });

结果

{'a': 3, 'b': 2, 'r': 2}

并使用

itertools::Itertools::group_by

let map2: HashMap<char, u32> = word.to_lowercase()
    .chars()
    .group_by(|&x| x)
    .into_iter()
    .map(|(k, v)| (k, v.count() as u32))
    .collect();

结果

{'r': 1, 'a': 1, 'b': 1}

奇怪的是,当输入字符串连续具有相同的字符时,

Itertools
会考虑这些字符。 问题是,是什么让它返回不同的结果?

游乐场

rust
3个回答
4
投票

您正在寻找

into_group_map_by
group_by
仅根据 docs 对连续元素进行分组。

use itertools::Itertools;
use std::collections::HashMap;

fn main() {
    let word = "Barbara";

    let map1 = word
        .to_lowercase()
        .chars()
        .fold(HashMap::new(), |mut acc, c| {
            *acc.entry(c).or_insert(0) += 1;
            acc
        });
    println!("{:?}", map1);

    let map2: HashMap<char, u32> = word
        .to_lowercase()
        .chars()
        .into_group_map_by(|&x| x)
        .into_iter()
        .map(|(k, v)| (k, v.len() as u32))
        .collect();
    println!("{:?}", map2);
}

输出:

{'b': 2, 'a': 3, 'r': 2}
{'b': 2, 'r': 2, 'a': 3}

游乐场

还有

into_grouping_map_by
,可以用于此目的,例如:

let map2: HashMap<char, u32> = word
    .to_lowercase()
    .chars()
    .into_grouping_map_by(|&x| x)
    .fold(0, |acc, _key, _value| acc + 1);

3
投票

文档说(强调):

fn group_by<K, F>(self, key: F) -> GroupBy<K, Self, F>
where
    Self: Sized,
    F: FnMut(&Self::Item) -> K,
    K: PartialEq, 

返回一个可以对迭代器元素进行分组的iterable。映射到相同键(“运行”)的连续元素被分配到同一组。

它只对连续的元素进行分组。在调用

group_by
之前,您需要对字符进行排序。

let map2: HashMap<char, u32> = word.to_lowercase()
    .chars()
    .sorted()
    .group_by(|&x| x)
    ...

输出:

{'a': 3, 'r': 2, 'b': 2}
{'b': 2, 'a': 3, 'r': 2}

游乐场


0
投票

Itertools 也有

counts
以方便使用:

use itertools::Itertools;

fn main() {
    let word = "Barbara";
    let map1 = word
        .to_lowercase()
        .chars()
        .counts();
    println!("{:?}", map1);
}

输出:

{'a': 3, 'r': 2, 'b': 2}

游乐场:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021

文档:https://docs.rs/itertools/latest/itertools/trait.Itertools.html#method.counts

让我意识到

counts
的GitHub问题:https://github.com/rust-itertools/itertools/issues/599

© www.soinside.com 2019 - 2024. All rights reserved.