File: RandomStableSample.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (69 lines) | stat: -rw-r--r-- 2,394 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Collections open source project
//
// Copyright (c) 2021 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//

// Note: This comes from swift-algorithms.

extension Collection {
  /// Randomly selects the specified number of elements from this collection,
  /// maintaining their relative order.
  ///
  /// - Parameters:
  ///   - k: The number of elements to randomly select.
  ///   - rng: The random number generator to use for the sampling.
  /// - Returns: An array of `k` random elements. If `k` is greater than this
  ///   collection's count, then this method returns the full collection.
  ///
  /// - Complexity: O(*n*), where *n* is the length of the collection.
  @inlinable
  public func randomStableSample<G: RandomNumberGenerator>(
    count k: Int, using rng: inout G
  ) -> [Element] {
    guard k > 0 else { return [] }
    
    var remainingCount = count
    guard k < remainingCount else { return Array(self) }
    
    var result: [Element] = []
    result.reserveCapacity(k)
    
    var i = startIndex
    var countToSelect = k
    while countToSelect > 0 {
      let r = Int.random(in: 0..<remainingCount, using: &rng)
      if r < countToSelect {
        result.append(self[i])
        countToSelect -= 1
      }

      formIndex(after: &i)
      remainingCount -= 1
    }
    
    return result
  }
  
  /// Randomly selects the specified number of elements from this collection,
  /// maintaining their relative order.
  ///
  /// This method is equivalent to calling `randomStableSample(k:using:)`,
  /// passing in the system's default random generator.
  ///
  /// - Parameter k: The number of elements to randomly select.
  /// - Returns: An array of `k` random elements. If `k` is greater than this
  ///   collection's count, then this method returns the full collection.
  ///
  /// - Complexity: O(*n*), where *n* is the length of the collection.
  @inlinable
  public func randomStableSample(count k: Int) -> [Element] {
    var g = SystemRandomNumberGenerator()
    return randomStableSample(count: k, using: &g)
  }
}