rust-itertools / itertools

Extra iterator adaptors, iterator methods, free functions, and macros.
https://docs.rs/itertools/
Apache License 2.0
2.7k stars 308 forks source link

`chunk_by` returns only the last value when collected #978

Open buinauskas opened 1 month ago

buinauskas commented 1 month ago
use std::collections::HashMap;
use itertools::Itertools;

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6];

    let chunks: HashMap<i32, Vec<i32>> = numbers
        .into_iter()
        .chunk_by(|number| number % 2)
        .into_iter()
        .map(|(k, v)| (k, v.collect()))
        .collect();

    let expectation = HashMap::from([
        (0, vec![2, 4, 6]),
        (1, vec![1, 3, 5]),
    ]);

    assert_eq!(chunks, expectation);
}

This is the full code and I would expect chunk_by to group elements by the result of closure and build a map out of it, however when running the equality assertion panics with:

assertion `left == right` failed
  left: {0: [6], 1: [5]}
 right: {1: [1, 3, 5], 0: [0, 2, 4, 6]}

Is that by design? The method example explicitly shows a loop when it iterates over the chunked results and does not call collect on the iterator.

phimuemue commented 1 month ago

I think it chunks consecutive, so that your example leads to 1-element-chunks. Then, collecting into hashmap will overwrite values if they’re already present. Try collecting into a Vec instead of Hashmap to see the result. I think you’re looking for group_by or similar (sorry, I’m on mobile and cannot look up the details.) Am Donnerstag, 1. August 2024, 20:22:37 MESZ hat Evaldas Buinauskas @.***> Folgendes geschrieben:

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

fn main() { let numbers = vec![1, 2, 3, 4, 5, 6];

let chunks: HashMap<i32, Vec<i32>> = numbers
    .into_iter()
    .chunk_by(|number| number % 2)
    .into_iter()
    .map(|(k, v)| (k, v.collect()))
    .collect();

let expectation = HashMap::from([
    (0, vec![0, 2, 4, 6]),
    (1, vec![1, 3, 5]),
]);

assert_eq!(chunks, expectation);

} This is the full code and I would expect chunk_by to group elements by the result of closure and build a map out of it, however when running the equality assertion panics with: assertion left == right failed left: {0: [6], 1: [5]} right: {1: [1, 3, 5], 0: [0, 2, 4, 6]}

Is that by design? The method example explicitly shows a loop when it iterates over the chunked results and does not call collect on the iterator.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>

buinauskas commented 1 month ago

In the past I used group_by and it has a deprecation warning telling me to use chunk_by, so that's what I did.

But apparently, there's into_group_map_by which does exactly what I'm after. This only left me with an open question whether that functionality is by design and whether it's expected.