<commit_before>//
//  Analysis.swift
//  
//
//  Created by <NAME> on 11/11/2016.
//
//

import Foundation

enum LengthOption {
  case word
  case sentence
}

struct Analysis {
  typealias Percentage = Double
  typealias Characters = Double
  
  let input: String
  let sentences: [String]
  let words: [String]
  let characters: [Character]
  
  init(of string: String) {
    input = string
    sentences = input
      .replacingOccurrences(of: "! ", with: "!\n")
      .replacingOccurrences(of: ". ", with: ".\n")
      .replacingOccurrences(of: "? ", with: "?\n").lines
      .filter { !$0.isEmpty }
    words = input.characters
      .split(separator: " ")
      .map(String.init)
      .map { $0.trimmingCharacters(in: CharacterSet.letters.inverted) }
    characters = Array(input.characters)
  }
  
  static func of(_ string: String) -> Analysis {
    return Analysis(of: string)
  }
  
  func sentenceCount() -> Int {
    return sentences.count
  }
  
  func wordCount(unique: Bool = false) -> Int {
    if unique {
      return _wordOccurrences().keys.count
    } else {
      return words.count
    }
  }
  
  func characterCount(includingSpaces: Bool = true) -> Int {
    if includingSpaces {
      return characters.count
    } else {
      return characters.filter { $0 != " " }.count
    }
  }
  
  private func _wordOccurrences(caseSensitive: Bool = false) -> [String: Int] {
    var occurrences: [String: Int] = [:]
    words
      .map { (caseSensitive) ? $0 : $0.lowercased() }
      .map { occurrences[$0] = (occurrences[$0] ?? 0) + 1 }
    return occurrences
  }
  
  private func _characterOccurences(caseSensitive: Bool = false) -> [Character: Int] {
    var occurrences: [Character: Int] = [:]
    characters
      .map { (caseSensitive) ? $0 : Character(String(describing: $0).lowercased()) }
      .map { occurrences[$0] = (occurrences[$0] ?? 0) + 1 }
    return occurrences
  }
  
  func wordOccurrences(caseSensitive: Bool = false) -> [String: Int] {
    return _wordOccurrences(caseSensitive: caseSensitive)
  }
  
  func characterOccurences(caseSensitive: Bool = false) -> [Character: Int] {
    return _characterOccurences(caseSensitive: caseSensitive)
  }
  
  func occurrences(of word: String, caseSensitive: Bool = false) -> Int {
    let word = (caseSensitive) ? word : word.lowercased()
    return _wordOccurrences(caseSensitive: caseSensitive)[word] ?? 0
  }
  
  func occurrences(of character: Character, caseSensitive: Bool = false) -> Int {
    let character = (caseSensitive) ? character : Character(String(describing: character).lowercased())
    return characters
      .map { (caseSensitive) ? $0 : Character(String(describing: $0).lowercased()) }
      .filter { $0 == character }.count<commit_msg>Replace map with forEach where possible<commit_after>//
//  Analysis.swift
//  
//
//  Created by <NAME> on 11/11/2016.
//
//

import Foundation

enum LengthOption {
  case word
  case sentence
}

struct Analysis {
  typealias Percentage = Double
  typealias Characters = Double
  
  let input: String
  let sentences: [String]
  let words: [String]
  let characters: [Character]
  
  init(of string: String) {
    input = string
    sentences = input
      .replacingOccurrences(of: "! ", with: "!\n")
      .replacingOccurrences(of: ". ", with: ".\n")
      .replacingOccurrences(of: "? ", with: "?\n").lines
      .filter { !$0.isEmpty }
    words = input.characters
      .split(separator: " ")
      .map(String.init)
      .map { $0.trimmingCharacters(in: CharacterSet.letters.inverted) }
    characters = Array(input.characters)
  }
  
  static func of(_ string: String) -> Analysis {
    return Analysis(of: string)
  }
  
  func sentenceCount() -> Int {
    return sentences.count
  }
  
  func wordCount(unique: Bool = false) -> Int {
    if unique {
      return _wordOccurrences().keys.count
    } else {
      return words.count
    }
  }
  
  func characterCount(includingSpaces: Bool = true) -> Int {
    if includingSpaces {
      return characters.count
    } else {
      return characters.filter { $0 != " " }.count
    }
  }
  
  private func _wordOccurrences(caseSensitive: Bool = false) -> [String: Int] {
    var occurrences: [String: Int] = [:]
    words
      .map { (caseSensitive) ? $0 : $0.lowercased() }
      .forEach { occurrences[$0] = (occurrences[$0] ?? 0) + 1 }
    return occurrences
  }
  
  private func _characterOccurences(caseSensitive: Bool = false) -> [Character: Int] {
    var occurrences: [Character: Int] = [:]
    characters
      .map { (caseSensitive) ? $0 : Character(String(describing: $0).lowercased()) }
      .forEach { occurrences[$0] = (occurrences[$0] ?? 0) + 1 }
    return occurrences
  }
  
  func wordOccurrences(caseSensitive: Bool = false) -> [String: Int] {
    return _wordOccurrences(caseSensitive: caseSensitive)
  }
  
  func characterOccurences(caseSensitive: Bool = false) -> [Character: Int] {
    return _characterOccurences(caseSensitive: caseSensitive)
  }
  
  func occurrences(of word: String, caseSensitive: Bool = false) -> Int {
    let word = (caseSensitive) ? word : word.lowercased()
    return _wordOccurrences(caseSensitive: caseSensitive)[word] ?? 0
  }
  
  func occurrences(of character: Character, caseSensitive: Bool = false) -> Int {
    let character = (caseSensitive) ? character : Character(String(describing: character).lowercased())
    return characters
      .map { (caseSensitive) ? $0 : Character(String(describing: $0).lowercased()) }
      .filter { $0 == character }.count
{'fraction_non_alphanumeric': 0.13379260333575055, 'fraction_numerical': 0.009789702683103698, 'mean_word_length': 2.997826086956522, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '2111736', 'n_tokens_mistral': 1867, 'n_tokens_neox': 1752, 'n_words': 422}