ArrayExtensions.swift 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. //
  2. // ArrayExtensions.swift
  3. // EZSwiftExtensions
  4. //
  5. // Created by Goktug Yilmaz on 15/07/15.
  6. // Copyright (c) 2015 Goktug Yilmaz. All rights reserved.
  7. //
  8. import Foundation
  9. public func ==<T: Equatable>(lhs: [T]?, rhs: [T]?) -> Bool {
  10. switch (lhs, rhs) {
  11. case let (lhs?, rhs?):
  12. return lhs == rhs
  13. case (.none, .none):
  14. return true
  15. default:
  16. return false
  17. }
  18. }
  19. extension Array {
  20. /// EZSE: Checks if array contains at least 1 item which type is same with given element's type
  21. public func containsType<T>(of element: T) -> Bool {
  22. let elementType = type(of: element)
  23. return contains { type(of: $0) == elementType}
  24. }
  25. /// EZSE: Decompose an array to a tuple with first element and the rest
  26. public func decompose() -> (head: Iterator.Element, tail: SubSequence)? {
  27. return (count > 0) ? (self[0], self[1..<count]) : nil
  28. }
  29. /// EZSE: Iterates on each element of the array with its index. (Index, Element)
  30. public func forEachEnumerated(_ body: @escaping (_ offset: Int, _ element: Element) -> Void) {
  31. enumerated().forEach(body)
  32. }
  33. /// EZSE: Gets the object at the specified index, if it exists.
  34. public func get(at index: Int) -> Element? {
  35. guard index >= 0 && index < count else { return nil }
  36. return self[index]
  37. }
  38. /// EZSE: Prepends an object to the array.
  39. public mutating func insertFirst(_ newElement: Element) {
  40. insert(newElement, at: 0)
  41. }
  42. /// EZSE: Returns a random element from the array.
  43. public func random() -> Element? {
  44. guard count > 0 else { return nil }
  45. let index = Int(arc4random_uniform(UInt32(count)))
  46. return self[index]
  47. }
  48. /// EZSE: Reverse the given index. i.g.: reverseIndex(2) would be 2 to the last
  49. public func reverseIndex(_ index: Int) -> Int? {
  50. guard index >= 0 && index < count else { return nil }
  51. return Swift.max(count - 1 - index, 0)
  52. }
  53. /// EZSE: Shuffles the array in-place using the Fisher-Yates-Durstenfeld algorithm.
  54. public mutating func shuffle() {
  55. guard count > 1 else { return }
  56. var j: Int
  57. for i in 0..<(count-2) {
  58. j = Int(arc4random_uniform(UInt32(count - i)))
  59. if i != i+j { self.swapAt(i, i+j) }
  60. }
  61. }
  62. /// EZSE: Shuffles copied array using the Fisher-Yates-Durstenfeld algorithm, returns shuffled array.
  63. public func shuffled() -> Array {
  64. var result = self
  65. result.shuffle()
  66. return result
  67. }
  68. /// EZSE: Returns an array with the given number as the max number of elements.
  69. public func takeMax(_ n: Int) -> Array {
  70. return Array(self[0..<Swift.max(0, Swift.min(n, count))])
  71. }
  72. /// EZSE: Checks if test returns true for all the elements in self
  73. public func testAll(_ body: @escaping (Element) -> Bool) -> Bool {
  74. return !contains { !body($0) }
  75. }
  76. /// EZSE: Checks if all elements in the array are true or false
  77. public func testAll(is condition: Bool) -> Bool {
  78. return testAll { ($0 as? Bool) ?? !condition == condition }
  79. }
  80. }
  81. extension Array where Element: Equatable {
  82. /// EZSE: Checks if the main array contains the parameter array
  83. public func contains(_ array: [Element]) -> Bool {
  84. return array.testAll { self.index(of: $0) ?? -1 >= 0 }
  85. }
  86. /// EZSE: Checks if self contains a list of items.
  87. public func contains(_ elements: Element...) -> Bool {
  88. return elements.testAll { self.index(of: $0) ?? -1 >= 0 }
  89. }
  90. /// EZSE: Returns the indexes of the object
  91. public func indexes(of element: Element) -> [Int] {
  92. return enumerated().flatMap { ($0.element == element) ? $0.offset : nil }
  93. }
  94. /// EZSE: Returns the last index of the object
  95. public func lastIndex(of element: Element) -> Int? {
  96. return indexes(of: element).last
  97. }
  98. /// EZSE: Removes the first given object
  99. public mutating func removeFirst(_ element: Element) {
  100. guard let index = index(of: element) else { return }
  101. self.remove(at: index)
  102. }
  103. /// EZSE: Removes all occurrences of the given object(s), at least one entry is needed.
  104. public mutating func removeAll(_ firstElement: Element?, _ elements: Element...) {
  105. var removeAllArr = [Element]()
  106. if let firstElementVal = firstElement {
  107. removeAllArr.append(firstElementVal)
  108. }
  109. elements.forEach({element in removeAllArr.append(element)})
  110. removeAll(removeAllArr)
  111. }
  112. /// EZSE: Removes all occurrences of the given object(s)
  113. public mutating func removeAll(_ elements: [Element]) {
  114. // COW ensures no extra copy in case of no removed elements
  115. self = filter { !elements.contains($0) }
  116. }
  117. /// EZSE: Difference of self and the input arrays.
  118. public func difference(_ values: [Element]...) -> [Element] {
  119. var result = [Element]()
  120. elements: for element in self {
  121. for value in values {
  122. // if a value is in both self and one of the values arrays
  123. // jump to the next iteration of the outer loop
  124. if value.contains(element) {
  125. continue elements
  126. }
  127. }
  128. // element it's only in self
  129. result.append(element)
  130. }
  131. return result
  132. }
  133. /// EZSE: Intersection of self and the input arrays.
  134. public func intersection(_ values: [Element]...) -> Array {
  135. var result = self
  136. var intersection = Array()
  137. for (i, value) in values.enumerated() {
  138. // the intersection is computed by intersecting a couple per loop:
  139. // self n values[0], (self n values[0]) n values[1], ...
  140. if i > 0 {
  141. result = intersection
  142. intersection = Array()
  143. }
  144. // find common elements and save them in first set
  145. // to intersect in the next loop
  146. value.forEach { (item: Element) -> Void in
  147. if result.contains(item) {
  148. intersection.append(item)
  149. }
  150. }
  151. }
  152. return intersection
  153. }
  154. /// EZSE: Union of self and the input arrays.
  155. public func union(_ values: [Element]...) -> Array {
  156. var result = self
  157. for array in values {
  158. for value in array {
  159. if !result.contains(value) {
  160. result.append(value)
  161. }
  162. }
  163. }
  164. return result
  165. }
  166. /// EZSE: Returns an array consisting of the unique elements in the array
  167. public func unique() -> Array {
  168. return reduce([]) { $0.contains($1) ? $0 : $0 + [$1] }
  169. }
  170. // MARK:- 获取帐号中的中文名称
  171. func getChinaName() ->[String]{
  172. let result = self
  173. var arrTemp = [String]()
  174. for userName in result{
  175. if let strUserName = userName as? String {
  176. if !strUserName.isBlank{
  177. let userNameSplit = strUserName.split("@");
  178. arrTemp.append(userNameSplit[0])
  179. }
  180. }
  181. }
  182. return arrTemp;
  183. }
  184. }
  185. extension Array where Element: Hashable {
  186. /// EZSE: Removes all occurrences of the given object(s)
  187. public mutating func removeAll(_ elements: [Element]) {
  188. let elementsSet = Set(elements)
  189. // COW ensures no extra copy in case of no removed elements
  190. self = filter { !elementsSet.contains($0) }
  191. }
  192. }
  193. extension Collection where Indices.Iterator.Element == Index {
  194. /// Returns the element at the specified index if it is within bounds, otherwise nil.
  195. public subscript (safe index: Index) -> Iterator.Element? {
  196. return indices.contains(index) ? self[index] : nil
  197. }
  198. }