rust-itertools / itertools

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

Feature request: `filter_parition` #658

Open Scripter17 opened 1 year ago

Scripter17 commented 1 year ago

Starting with the use case that prompted this:

fn get_dir(path: &path::Path) -> io::Result<(Vec<fs::DirEntry>, Vec<fs::DirEntry>)> {
    path.read_dir()?
        .filter_map(|content| content.ok())
        .filter_partition(|content| content.file_type().ok().and_then(|file_type| file_type.is_file())
}

Basically the same thing as the normal partition but the provided function has 3 return values:

Without filter_partition the best way I can think to get separate lists of files and folders is this:

fn get_dir(path: &path::Path) -> io::Result<(Vec<fs::DirEntry>, Vec<fs::DirEntry>)> {
    path.read_dir()?
        .filter_map(|content| content.ok())
        .filter(|content| content.file_type().is_ok())
        .partition(|content| content.file_type().expect("content.file_type() to be Ok").is_file())
}

Which shouldn't ever cause issues unless a file's/folder's permissions are changed while the function is running, but that'd probably cause issues later on anyway.

khoover commented 1 year ago

EDIT: Dunno how I missed this, but there's partition_map. So your example would just be:

fn get_dir(path: &path::Path) -> io::Result<(Vec<fs::DirEntry>, Vec<fs::DirEntry>)> {
    Ok(path.read_dir()?
        .filter_map(|content| content.ok())
        .filter_map(|content| content.file_type().ok().map(|file_type|
            if file_type.is_file() {
                Either::Left(content)
            } else {
                Either::Right(content)
            }
        ))
        .partition_map(|x| x))
}
scottmcm commented 1 year ago

👍 to .partition_map(identity) here.