#iterator #range-iterator #numeric

无std iter_num_tools

创建非整数范围的简单迭代器。itertools + num = iter_num_tools

29个版本

0.7.1 2023年4月21日
0.7.0 2023年4月21日
0.6.2 2021年11月28日
0.6.1 2021年6月18日
0.1.17 2020年12月26日

数学分类中排名第125

Download history 19/week @ 2024-03-13 14/week @ 2024-03-20 20/week @ 2024-03-27 34/week @ 2024-04-03 35/week @ 2024-04-10 61/week @ 2024-04-17 37/week @ 2024-04-24 49/week @ 2024-05-01 41/week @ 2024-05-08 14/week @ 2024-05-15 26/week @ 2024-05-22 38/week @ 2024-05-29 144/week @ 2024-06-05 114/week @ 2024-06-12 176/week @ 2024-06-19 192/week @ 2024-06-26

每月下载量636

MIT许可协议

47KB
846 代码行

iter-num-tools

Build Status Rust Documentation Latest Version Code Coverage

这是一个利用数字属性进行大量扩展的迭代器集合。主要扩展了Range。

LinSpace

LinSpace是一个具有固定数量、均匀间隔值的范围迭代器。

use iter_num_tools::lin_space;

// Count from 1.0 up to and including 5.0, with 5 numbers counted in total
let it = lin_space(1.0..=5.0, 5);
assert!(it.eq([1.0, 2.0, 3.0, 4.0, 5.0]));

// Count from 0.0 up to and excluding 5.0, with 5 numbers counted in total
let it = lin_space(0.0..5.0, 5);
assert!(it.eq([0.0, 1.0, 2.0, 3.0, 4.0]));

GridSpace

GridSpace扩展了LinSpace

use iter_num_tools::grid_space;

// count in 2 dimensions (excluding end points),
// from 0.0 up to 1.0 in the x direction with 2 even steps,
// and 0.0 up to 2.0 in the y direction with 4 even steps
let it = grid_space([0.0, 0.0]..[1.0, 2.0], [2, 4]);
assert!(it.eq([
    [0.0, 0.0], [0.5, 0.0],
    [0.0, 0.5], [0.5, 0.5],
    [0.0, 1.0], [0.5, 1.0],
    [0.0, 1.5], [0.5, 1.5],
]));

// count in 2 dimensions (including end points),
// from 0.0 up to 1.0 in the x direction,
// and 0.0 up to 2.0 in the y direction with 3 even steps in all directions
let it = grid_space([0.0, 0.0]..=[1.0, 2.0], 3);
assert!(it.eq([
    [0.0, 0.0], [0.5, 0.0], [1.0, 0.0],
    [0.0, 1.0], [0.5, 1.0], [1.0, 1.0],
    [0.0, 2.0], [0.5, 2.0], [1.0, 2.0],
]));

Arange

Arange与LinSpace类似,但步骤数量不是固定的,而是以固定数量进行。

use iter_num_tools::arange;

let it = arange(0.0..2.0, 0.5);
assert!(it.eq([0.0, 0.5, 1.0, 1.5]));

注意

没有inclusive版本的arange。考虑以下情况

use iter_num_tools::arange;

let it = arange(0.0..=2.1, 0.5);

我们不期望2.1将是迭代器将遇到的值,但范围表明它应该包含在内。因此,没有提供RangeInclusive实现。

ArangeGrid

ArangeGrid与GridSpace相同,但用于Arange而不是LinSpace

use iter_num_tools::arange_grid;

// count in 2 dimensions,
// from 0.0 up to 1.0 in the x direction,
// and 0.0 up to 2.0 in the y direction,
// stepping by 0.5 each time
let it = arange_grid([0.0, 0.0]..[1.0, 2.0], 0.5);
assert!(it.eq([
    [0.0, 0.0], [0.5, 0.0],
    [0.0, 0.5], [0.5, 0.5],
    [0.0, 1.0], [0.5, 1.0],
    [0.0, 1.5], [0.5, 1.5],
]));

// count in 2 dimensions,
// from 0.0 up to 1.0 in the x direction stepping by 0.5 each time,
// and 0.0 up to 2.0 in the y direction stepping by 1.0 each time
let it = arange_grid([0.0, 0.0]..[1.0, 2.0], [0.5, 1.0]);
assert!(it.eq([
    [0.0, 0.0], [0.5, 0.0],
    [0.0, 1.0], [0.5, 1.0],
]));

LogSpace

LogSpace与LinSpace类似,但步骤是均匀间隔的对数步骤,而不是均匀间隔的线性步骤。

use iter_num_tools::log_space;
use itertools::zip_eq;

// From 1.0 up to and including 1000.0, taking 4 logarithmic steps
let it = log_space(1.0..=1000.0, 4);
let expected: [f64; 4] = [1.0, 10.0, 100.0, 1000.0];

assert!(zip_eq(it, expected).all(|(x, y)| (x-y).abs() < 1e-10));

// From 1.0 up to 1000.0, taking 3 logarithmic steps
let it = log_space(1.0..1000.0, 3);
let expected: [f64; 3] = [1.0, 10.0, 100.0];

assert!(zip_eq(it, expected).all(|(x, y)| (x-y).abs() < 1e-10));

替代方案

已经有一个名为itertools-num的项目,它有相当多的下载,但它没有针对速度或灵活性进行优化。

(尝试自己进行基准测试:克隆仓库并运行 cargo bench --bench "linspace" --all-features)

LinSpace/linspace [1.0, 3.0] x100 (iter-num-tools)
                        time:   [65.311 ns 65.579 ns 65.898 ns]
LinSpace/linspace [1.0, 3.0] x100 (std)
                        time:   [67.545 ns 67.762 ns 68.047 ns]
LinSpace/linspace [1.0, 3.0] x100 (itertools-num)
                        time:   [117.05 ns 117.59 ns 118.23 ns]
fn bench(i: impl Iterator<Item=f64>) -> Vec<f64> {
    black_box(i.map(|x| x * 2.0).collect())
}

// first benchmark (fastest)
bench(iter_num_tools::lin_space(1.0..=3.0, 100));

// second benchmark
fn lin_space_std(start: f64, end: f64, steps: usize) -> impl Iterator<Item = f64> {
    let len = end - start;
    let step = len / steps as f64;
    (0..=steps).map(move |i| start + i as f64 * step)
}
bench(lin_space_std(1.0, 3.0, 100));

// third benchmark (slowest)
bench(itertools_num::linspace(1.0, 3.0, 100));

它也没有提供任何其他实用工具。只有linspace(inclusive)和一个“累积和”迭代器适配器。

依赖关系

~575KB
~11K SLoC