// Store values with indices to handle duplicates uniquely private struct Entry: Comparable { let index: Int let value: T static func < (lhs: Entry, rhs: Entry) -> Bool { lhs.value == rhs.value ? lhs.index < rhs.index : lhs.value < rhs.value } } extension Sequence { /// Applies a centered median filter to the sequence. /// - Parameters: /// - windowSize: The number of samples in the median filter window (should be odd for symmetric centering). /// - transform: Closure to transform each element into a numeric value. /// - Returns: An array of filtered elements (same type as input). func medianFiltered(windowSize: Int, transform: (Element) -> T) -> [Element] { precondition(windowSize > 0, "Window size must be greater than zero") let input = Array(self) guard !input.isEmpty else { return [] } var result: [Element] = [] result.reserveCapacity(input.count) let halfWindow = windowSize / 2 for i in 0..] = [] for j in start...end { window.append(Entry(index: j, value: transform(input[j]))) } window.sort() // Median position let medianIndex = window.count / 2 let medianValue = window[medianIndex].value // Choose the element closest to the median let closest = input[start...end] .min(by: { abs(Double(transform($0) - medianValue)) < abs(Double(transform($1) - medianValue)) })! result.append(closest) } return result } /// Default version when Element itself is BinaryFloatingPoint func medianFiltered(windowSize: Int) -> [Element] where Element: BinaryFloatingPoint { return self.medianFiltered(windowSize: windowSize, transform: { $0 }) } /// Iterate over adjacent pairs of elements in the sequence, applying a transform closure. /// - Parameter transform: A closure that takes two consecutive elements and returns a value of type T. /// - Returns: An array of transformed values. func adjacentPairs(_ transform: (Element, Element) -> T) -> [T] { var result: [T] = [] var iterator = self.makeIterator() guard var prev = iterator.next() else { return [] } while let current = iterator.next() { result.append(transform(prev, current)) prev = current } return result } } // MARK: - Helpers extension Array where Element: Comparable { /// Binary search returning the index where `predicate` fails (insertion point). func binarySearch(predicate: (Element) -> Bool) -> Int { var low = 0 var high = count while low < high { let mid = (low + high) / 2 if predicate(self[mid]) { low = mid + 1 } else { high = mid } } return low } /// Binary search exact element index if present. func binarySearchExact(_ element: Element) -> Int? { var low = 0 var high = count - 1 while low <= high { let mid = (low + high) / 2 if self[mid] == element { return mid } else if self[mid] < element { low = mid + 1 } else { high = mid - 1 } } return nil } }