@@ -2254,6 +2254,316 @@ pub trait Itertools : Iterator {
2254
2254
)
2255
2255
}
2256
2256
2257
+ /// Return the position of the maximum element in the iterator.
2258
+ ///
2259
+ /// If several elements are equally maximum, the position of the
2260
+ /// last of them is returned.
2261
+ ///
2262
+ /// # Examples
2263
+ ///
2264
+ /// ```
2265
+ /// use itertools::Itertools;
2266
+ ///
2267
+ /// let a: [i32; 0] = [];
2268
+ /// assert_eq!(a.iter().position_max(), None);
2269
+ ///
2270
+ /// let a = [-3, 0, 1, 5, -10];
2271
+ /// assert_eq!(a.iter().position_max(), Some(3));
2272
+ ///
2273
+ /// let a = [1, 1, -1, -1];
2274
+ /// assert_eq!(a.iter().position_max(), Some(1));
2275
+ /// ```
2276
+ fn position_max ( self ) -> Option < usize >
2277
+ where Self : Sized , Self :: Item : Ord
2278
+ {
2279
+ self . enumerate ( )
2280
+ . max_by ( |x, y| Ord :: cmp ( & x. 1 , & y. 1 ) )
2281
+ . map ( |x| x. 0 )
2282
+ }
2283
+
2284
+ /// Return the position of the maximum element in the iterator, as
2285
+ /// determined by the specified function.
2286
+ ///
2287
+ /// If several elements are equally maximum, the position of the
2288
+ /// last of them is returned.
2289
+ ///
2290
+ /// # Examples
2291
+ ///
2292
+ /// ```
2293
+ /// use itertools::Itertools;
2294
+ ///
2295
+ /// let a: [i32; 0] = [];
2296
+ /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), None);
2297
+ ///
2298
+ /// let a = [-3_i32, 0, 1, 5, -10];
2299
+ /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), Some(4));
2300
+ ///
2301
+ /// let a = [1_i32, 1, -1, -1];
2302
+ /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), Some(3));
2303
+ /// ```
2304
+ fn position_max_by_key < K , F > ( self , mut key : F ) -> Option < usize >
2305
+ where Self : Sized , K : Ord , F : FnMut ( & Self :: Item ) -> K
2306
+ {
2307
+ self . enumerate ( )
2308
+ . max_by ( |x, y| Ord :: cmp ( & key ( & x. 1 ) , & key ( & y. 1 ) ) )
2309
+ . map ( |x| x. 0 )
2310
+ }
2311
+
2312
+ /// Return the position of the maximum element in the iterator, as
2313
+ /// determined by the specified comparison function.
2314
+ ///
2315
+ /// If several elements are equally maximum, the position of the
2316
+ /// last of them is returned.
2317
+ ///
2318
+ /// # Examples
2319
+ ///
2320
+ /// ```
2321
+ /// use itertools::Itertools;
2322
+ ///
2323
+ /// let a: [i32; 0] = [];
2324
+ /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), None);
2325
+ ///
2326
+ /// let a = [-3_i32, 0, 1, 5, -10];
2327
+ /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), Some(3));
2328
+ ///
2329
+ /// let a = [1_i32, 1, -1, -1];
2330
+ /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), Some(1));
2331
+ /// ```
2332
+ fn position_max_by < F > ( self , mut compare : F ) -> Option < usize >
2333
+ where Self : Sized , F : FnMut ( & Self :: Item , & Self :: Item ) -> Ordering
2334
+ {
2335
+ self . enumerate ( )
2336
+ . max_by ( |x, y| compare ( & x. 1 , & y. 1 ) )
2337
+ . map ( |x| x. 0 )
2338
+ }
2339
+
2340
+ /// Return the position of the minimum element in the iterator.
2341
+ ///
2342
+ /// If several elements are equally minimum, the position of the
2343
+ /// first of them is returned.
2344
+ ///
2345
+ /// # Examples
2346
+ ///
2347
+ /// ```
2348
+ /// use itertools::Itertools;
2349
+ ///
2350
+ /// let a: [i32; 0] = [];
2351
+ /// assert_eq!(a.iter().position_min(), None);
2352
+ ///
2353
+ /// let a = [-3, 0, 1, 5, -10];
2354
+ /// assert_eq!(a.iter().position_min(), Some(4));
2355
+ ///
2356
+ /// let a = [1, 1, -1, -1];
2357
+ /// assert_eq!(a.iter().position_min(), Some(2));
2358
+ /// ```
2359
+ fn position_min ( self ) -> Option < usize >
2360
+ where Self : Sized , Self :: Item : Ord
2361
+ {
2362
+ self . enumerate ( )
2363
+ . min_by ( |x, y| Ord :: cmp ( & x. 1 , & y. 1 ) )
2364
+ . map ( |x| x. 0 )
2365
+ }
2366
+
2367
+ /// Return the position of the minimum element in the iterator, as
2368
+ /// determined by the specified function.
2369
+ ///
2370
+ /// If several elements are equally minimum, the position of the
2371
+ /// first of them is returned.
2372
+ ///
2373
+ /// # Examples
2374
+ ///
2375
+ /// ```
2376
+ /// use itertools::Itertools;
2377
+ ///
2378
+ /// let a: [i32; 0] = [];
2379
+ /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), None);
2380
+ ///
2381
+ /// let a = [-3_i32, 0, 1, 5, -10];
2382
+ /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), Some(1));
2383
+ ///
2384
+ /// let a = [1_i32, 1, -1, -1];
2385
+ /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), Some(0));
2386
+ /// ```
2387
+ fn position_min_by_key < K , F > ( self , mut key : F ) -> Option < usize >
2388
+ where Self : Sized , K : Ord , F : FnMut ( & Self :: Item ) -> K
2389
+ {
2390
+ self . enumerate ( )
2391
+ . min_by ( |x, y| Ord :: cmp ( & key ( & x. 1 ) , & key ( & y. 1 ) ) )
2392
+ . map ( |x| x. 0 )
2393
+ }
2394
+
2395
+ /// Return the position of the minimum element in the iterator, as
2396
+ /// determined by the specified comparison function.
2397
+ ///
2398
+ /// If several elements are equally minimum, the position of the
2399
+ /// first of them is returned.
2400
+ ///
2401
+ /// # Examples
2402
+ ///
2403
+ /// ```
2404
+ /// use itertools::Itertools;
2405
+ ///
2406
+ /// let a: [i32; 0] = [];
2407
+ /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), None);
2408
+ ///
2409
+ /// let a = [-3_i32, 0, 1, 5, -10];
2410
+ /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), Some(4));
2411
+ ///
2412
+ /// let a = [1_i32, 1, -1, -1];
2413
+ /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), Some(2));
2414
+ /// ```
2415
+ fn position_min_by < F > ( self , mut compare : F ) -> Option < usize >
2416
+ where Self : Sized , F : FnMut ( & Self :: Item , & Self :: Item ) -> Ordering
2417
+ {
2418
+ self . enumerate ( )
2419
+ . min_by ( |x, y| compare ( & x. 1 , & y. 1 ) )
2420
+ . map ( |x| x. 0 )
2421
+ }
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 self . enumerate ( ) . minmax_by_key ( |e| key ( & e. 1 ) ) {
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 self . enumerate ( ) . minmax_by ( |x, y| compare ( & x. 1 , & y. 1 ) ) {
2561
+ NoElements => NoElements ,
2562
+ OneElement ( x) => OneElement ( x. 0 ) ,
2563
+ MinMax ( x, y) => MinMax ( x. 0 , y. 0 ) ,
2564
+ }
2565
+ }
2566
+
2257
2567
/// If the iterator yields exactly one element, that element will be returned, otherwise
2258
2568
/// an error will be returned containing an iterator that has the same output as the input
2259
2569
/// iterator.
0 commit comments