<commit_before>//
//  Collection.swift
//
//  CotEditor
//  https://coteditor.com
//
//  Created by 1024jp on 2016-06-27.
//
//  ---------------------------------------------------------------------------
//
//  © 2016-2019 1024jp
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  https://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

extension RangeReplaceableCollection where Element: Equatable {
    
    /// Remove first collection element that is equal to the given `element`.
    ///
    /// - Parameter element: The element to be removed.
    mutating func remove(_ element: Element) {
        
        if let index = self.firstIndex(of: element) {
            self.remove(at: index)
        }
    }
    
}



extension Collection {

    /// Return the element at the specified index only if it is within bounds, otherwise nil.
    ///
    /// - Parameter index: The position of the element to obtain.
    subscript(safe index: Index) -> Element? {
        
        return self.indices.contains(index) ? self[index] : nil
    }
    
}



extension Sequence where Element: Equatable {
    
    /// An array consists of unique elements of receiver keeping ordering.
    var unique: [Element] {
        
        return self.reduce(into: []) { (unique, element) in
            guard !unique.contains(element) else { return }
            
            unique.append(element)
        }
    }
    
}



extension Dictionary {
    
    /// Return a new dictionary containing the keys transformed by the given closure with the values of this dictionary.
    ///
    /// - Parameter transform: A closure that transforms a key. Every transformed key must be unique.
    /// - Returns: A dictionary containing transformed keys and the values of this dictionary.
    func mapKeys<T>(transform: (Key) throws -> T) rethrows -> [T: Value] {
        
        let keysWithValues = try self.map { (key, value) -> (T, Value) in
             (try transform(key), value)
        }
        
        return [T: Value](uniqueKeysWithValues: keysWithValues)
    }
    
}



// MARK: - Count

enum QuantityComparisonResult {
    
    case less, equal, greater
}


extension Sequence {
    
    /// Count up elements that satisfy the given predicate.
    ///
    /// - Parameters:
    ///    - predicate: A closure that takes an element of the sequence as its argument
    ///                 and returns a Boolean value indicating whether the element should be counted.
    /// - Returns: The number of elements that satisfies the given predicate.
    func count(where predicate: (Element) throws -> Bool) rethrows -> Int {
        
        return try self.reduce(0) { try predicate($1) ? $0 + 1 : $0 }
    }
    
    
    /// Count up elements by enumerating collection until a element shows up that doesn't satisfy the given predicate.
    ///
    /// - Parameters:
    ///    - predicate: A closure that takes an element of the sequence as its argument
    ///                 and returns a Boolean value indicating whether the element should be counted.
    /// - Returns: The number of elements that satisfies the given predicate and are sequentially from the first index.
    func countPrefix(while predicate: (Element) throws -> Bool) rethrows -> Int {
        
        return try self.lazy.prefix(while: predicate).count
    }
    
    
    /// Performance efficient way to compare the number of elements with the given number.
    ///
    /// - Note: This method takes advantage especially when counting elements is heavy (such as String count) and the number to compare is small.
    ///
    /// - Parameter number: The number of elements to test.
    /// - Returns: The result whether the number of the elements in the receiver is less than, equal, or more than the given number.
    func compareCount(with number: Int) -> QuantityComparisonResult {
        
        assert(number >= 0, "The count number to compare should be a natural number.")
        
        guard number >= 0 else { return .greater }
        
        var count = 0
        for _ in self {
            count += 1
            if count > number { return .greater }
        }
        
        return (count == number) ? .equal : .less
    }
    
}
<commit_msg>Use guard instead of if<commit_after>//
//  Collection.swift
//
//  CotEditor
//  https://coteditor.com
//
//  Created by 1024jp on 2016-06-27.
//
//  ---------------------------------------------------------------------------
//
//  © 2016-2019 1024jp
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  https://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

extension RangeReplaceableCollection where Element: Equatable {
    
    /// Remove first collection element that is equal to the given `element`.
    ///
    /// - Parameter element: The element to be removed.
    mutating func remove(_ element: Element) {
        
        guard let index = self.firstIndex(of: element) else { return }
        
        self.remove(at: index)
    }
    
}



extension Collection {

    /// Return the element at the specified index only if it is within bounds, otherwise nil.
    ///
    /// - Parameter index: The position of the element to obtain.
    subscript(safe index: Index) -> Element? {
        
        return self.indices.contains(index) ? self[index] : nil
    }
    
}



extension Sequence where Element: Equatable {
    
    /// An array consists of unique elements of receiver keeping ordering.
    var unique: [Element] {
        
        return self.reduce(into: []) { (unique, element) in
            guard !unique.contains(element) else { return }
            
            unique.append(element)
        }
    }
    
}



extension Dictionary {
    
    /// Return a new dictionary containing the keys transformed by the given closure with the values of this dictionary.
    ///
    /// - Parameter transform: A closure that transforms a key. Every transformed key must be unique.
    /// - Returns: A dictionary containing transformed keys and the values of this dictionary.
    func mapKeys<T>(transform: (Key) throws -> T) rethrows -> [T: Value] {
        
        let keysWithValues = try self.map { (key, value) -> (T, Value) in
             (try transform(key), value)
        }
        
        return [T: Value](uniqueKeysWithValues: keysWithValues)
    }
    
}



// MARK: - Count

enum QuantityComparisonResult {
    
    case less, equal, greater
}


extension Sequence {
    
    /// Count up elements that satisfy the given predicate.
    ///
    /// - Parameters:
    ///    - predicate: A closure that takes an element of the sequence as its argument
    ///                 and returns a Boolean value indicating whether the element should be counted.
    /// - Returns: The number of elements that satisfies the given predicate.
    func count(where predicate: (Element) throws -> Bool) rethrows -> Int {
        
        return try self.reduce(0) { try predicate($1) ? $0 + 1 : $0 }
    }
    
    
    /// Count up elements by enumerating collection until a element shows up that doesn't satisfy the given predicate.
    ///
    /// - Parameters:
    ///    - predicate: A closure that takes an element of the sequence as its argument
    ///                 and returns a Boolean value indicating whether the element should be counted.
    /// - Returns: The number of elements that satisfies the given predicate and are sequentially from the first index.
    func countPrefix(while predicate: (Element) throws -> Bool) rethrows -> Int {
        
        return try self.lazy.prefix(while: predicate).count
    }
    
    
    /// Performance efficient way to compare the number of elements with the given number.
    ///
    /// - Note: This method takes advantage especially when counting elements is heavy (such as String count) and the number to compare is small.
    ///
    /// - Parameter number: The number of elements to test.
    /// - Returns: The result whether the number of the elements in the receiver is less than, equal, or more than the given number.
    func compareCount(with number: Int) -> QuantityComparisonResult {
        
        assert(number >= 0, "The count number to compare should be a natural number.")
        
        guard number >= 0 else { return .greater }
        
        var count = 0
        for _ in self {
            count += 1
            if count > number { return .greater }
        }
        
        return (count == number) ? .equal : .less
    }
    
}

{'fraction_non_alphanumeric': 0.10526315789473684, 'fraction_numerical': 0.007884082676326443, 'mean_word_length': 2.002879078694818, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 29, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1345200', 'n_tokens_mistral': 2415, 'n_tokens_neox': 2302, 'n_words': 1016}