itertools icon indicating copy to clipboard operation
itertools copied to clipboard

Feature request: `filter_parition`

Open Scripter17 opened this issue 3 years ago • 2 comments

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:

  • None to drop the element
  • Some(true) to put the element in the left side of the tuple
  • Some(false) to put the element in the right side of the tuple

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.

Scripter17 avatar Nov 21 '22 07:11 Scripter17

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))
}

khoover avatar Dec 06 '22 19:12 khoover

👍 to .partition_map(identity) here.

scottmcm avatar Jun 17 '23 03:06 scottmcm