@@ -2420,6 +2420,154 @@ pub trait Itertools : Iterator {
2420
2420
. map ( |x| x. 0 )
2421
2421
}
2422
2422
2423
+ /// Return the positions of the minimum and maximum elements in
2424
+ /// the iterator.
2425
+ ///
2426
+ /// The return type [`MinMaxResult`] is an enum of three variants:
2427
+ ///
2428
+ /// - `NoElements` if the iterator is empty.
2429
+ /// - `OneElement(xpos)` if the iterator has exactly one element.
2430
+ /// - `MinMax(xpos, ypos)` is returned otherwise, where the
2431
+ /// element at `xpos` ≤ the element at `ypos`. While the
2432
+ /// referenced elements themselves may be equal, `xpos` cannot
2433
+ /// be equal to `ypos`.
2434
+ ///
2435
+ /// On an iterator of length `n`, `position_minmax` does `1.5 * n`
2436
+ /// comparisons, and so is faster than calling `positon_min` and
2437
+ /// `position_max` separately which does `2 * n` comparisons.
2438
+ ///
2439
+ /// For the minimum, if several elements are equally minimum, the
2440
+ /// position of the first of them is returned. For the maximum, if
2441
+ /// several elements are equally maximum, the position of the last
2442
+ /// of them is returned.
2443
+ ///
2444
+ /// The elements can be floats but no particular result is
2445
+ /// guaranteed if an element is NaN.
2446
+ ///
2447
+ /// # Examples
2448
+ ///
2449
+ /// ```
2450
+ /// use itertools::Itertools;
2451
+ /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax};
2452
+ ///
2453
+ /// let a: [i32; 0] = [];
2454
+ /// assert_eq!(a.iter().position_minmax(), NoElements);
2455
+ ///
2456
+ /// let a = [10];
2457
+ /// assert_eq!(a.iter().position_minmax(), OneElement(0));
2458
+ ///
2459
+ /// let a = [-3, 0, 1, 5, -10];
2460
+ /// assert_eq!(a.iter().position_minmax(), MinMax(4, 3));
2461
+ ///
2462
+ /// let a = [1, 1, -1, -1];
2463
+ /// assert_eq!(a.iter().position_minmax(), MinMax(2, 1));
2464
+ /// ```
2465
+ ///
2466
+ /// [`MinMaxResult`]: enum.MinMaxResult.html
2467
+ fn position_minmax ( self ) -> MinMaxResult < usize >
2468
+ where Self : Sized , Self :: Item : PartialOrd
2469
+ {
2470
+ use MinMaxResult :: { NoElements , OneElement , MinMax } ;
2471
+ match minmax:: minmax_impl ( self . enumerate ( ) , |_| ( ) , |x, y, _, _| x. 1 < y. 1 ) {
2472
+ NoElements => NoElements ,
2473
+ OneElement ( x) => OneElement ( x. 0 ) ,
2474
+ MinMax ( x, y) => MinMax ( x. 0 , y. 0 ) ,
2475
+ }
2476
+ }
2477
+
2478
+ /// Return the postions of the minimum and maximum elements of an
2479
+ /// iterator, as determined by the specified function.
2480
+ ///
2481
+ /// The return value is a variant of [`MinMaxResult`] like for
2482
+ /// [`position_minmax`].
2483
+ ///
2484
+ /// For the minimum, if several elements are equally minimum, the
2485
+ /// position of the first of them is returned. For the maximum, if
2486
+ /// several elements are equally maximum, the position of the last
2487
+ /// of them is returned.
2488
+ ///
2489
+ /// The keys can be floats but no particular result is guaranteed
2490
+ /// if a key is NaN.
2491
+ ///
2492
+ /// # Examples
2493
+ ///
2494
+ /// ```
2495
+ /// use itertools::Itertools;
2496
+ /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax};
2497
+ ///
2498
+ /// let a: [i32; 0] = [];
2499
+ /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), NoElements);
2500
+ ///
2501
+ /// let a = [10_i32];
2502
+ /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), OneElement(0));
2503
+ ///
2504
+ /// let a = [-3_i32, 0, 1, 5, -10];
2505
+ /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), MinMax(1, 4));
2506
+ ///
2507
+ /// let a = [1_i32, 1, -1, -1];
2508
+ /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), MinMax(0, 3));
2509
+ /// ```
2510
+ ///
2511
+ /// [`MinMaxResult`]: enum.MinMaxResult.html
2512
+ /// [`position_minmax`]: #method.position_minmax
2513
+ fn position_minmax_by_key < K , F > ( self , mut key : F ) -> MinMaxResult < usize >
2514
+ where Self : Sized , K : PartialOrd , F : FnMut ( & Self :: Item ) -> K
2515
+ {
2516
+ use MinMaxResult :: { NoElements , OneElement , MinMax } ;
2517
+ match minmax:: minmax_impl ( self . enumerate ( ) , |x| key ( & x. 1 ) , |_, _, xk, yk| xk < yk) {
2518
+ NoElements => NoElements ,
2519
+ OneElement ( x) => OneElement ( x. 0 ) ,
2520
+ MinMax ( x, y) => MinMax ( x. 0 , y. 0 ) ,
2521
+ }
2522
+ }
2523
+
2524
+ /// Return the postions of the minimum and maximum elements of an
2525
+ /// iterator, as determined by the specified comparison function.
2526
+ ///
2527
+ /// The return value is a variant of [`MinMaxResult`] like for
2528
+ /// [`position_minmax`].
2529
+ ///
2530
+ /// For the minimum, if several elements are equally minimum, the
2531
+ /// position of the first of them is returned. For the maximum, if
2532
+ /// several elements are equally maximum, the position of the last
2533
+ /// of them is returned.
2534
+ ///
2535
+ /// # Examples
2536
+ ///
2537
+ /// ```
2538
+ /// use itertools::Itertools;
2539
+ /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax};
2540
+ ///
2541
+ /// let a: [i32; 0] = [];
2542
+ /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), NoElements);
2543
+ ///
2544
+ /// let a = [10_i32];
2545
+ /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), OneElement(0));
2546
+ ///
2547
+ /// let a = [-3_i32, 0, 1, 5, -10];
2548
+ /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), MinMax(4, 3));
2549
+ ///
2550
+ /// let a = [1_i32, 1, -1, -1];
2551
+ /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), MinMax(2, 1));
2552
+ /// ```
2553
+ ///
2554
+ /// [`MinMaxResult`]: enum.MinMaxResult.html
2555
+ /// [`position_minmax`]: #method.position_minmax
2556
+ fn position_minmax_by < F > ( self , mut compare : F ) -> MinMaxResult < usize >
2557
+ where Self : Sized , F : FnMut ( & Self :: Item , & Self :: Item ) -> Ordering
2558
+ {
2559
+ use MinMaxResult :: { NoElements , OneElement , MinMax } ;
2560
+ match minmax:: minmax_impl (
2561
+ self . enumerate ( ) ,
2562
+ |_| ( ) ,
2563
+ |x, y, _, _| Ordering :: Less == compare ( & x. 1 , & y. 1 )
2564
+ ) {
2565
+ NoElements => NoElements ,
2566
+ OneElement ( x) => OneElement ( x. 0 ) ,
2567
+ MinMax ( x, y) => MinMax ( x. 0 , y. 0 ) ,
2568
+ }
2569
+ }
2570
+
2423
2571
/// If the iterator yields exactly one element, that element will be returned, otherwise
2424
2572
/// an error will be returned containing an iterator that has the same output as the input
2425
2573
/// iterator.
0 commit comments