[Swift] あると便利（かも）な 演算子

**便利（かも）な 演算子 をいくつか紹介します**

# 1. 切り上げる整数除算演算子

普通の整数除算は`切り捨て`ですが、`切り上げる`整数除算演算子 `/^`

```swift
infix operator /^  : MultiplicationPrecedence
infix operator /^= : AssignmentPrecedence
@inlinable func /^  <T: FixedWidthInteger>(lhs: T, rhs: T) -> T { (lhs + (rhs - 1)) / rhs }
@inlinable func /^= <T: FixedWidthInteger>(lhs: inout T, rhs: T) { lhs = (lhs + (rhs - 1)) / rhs }
```

なお、対象は正数のみで、負数を考慮していません。（使う場面がなかったので・・・悪しからず）
（`if`文にて場合分けするだけですが・・・）



↓ 使用例です。

```swift:使用例
var A = 10 /^ 3  
//4

A /^= 3  
//2

let B = 12 /^ 3  
//4

let C = 13 /^ 3  
//5
```

# 2. MOD演算子`%%`

Swift標準のMOD演算子`%`と、負数の場合の結果が異なる（最小非負剰余の）`%%`演算子を定義します。_（ Python の % に同じ）_
（除数と符号が同じになる結果を返します）

```swift
infix operator %% : MultiplicationPrecedence // modulo
@inlinable func %%(lhs: Int, rhs: Int) -> Int { ((lhs % rhs) + rhs) % rhs }
```

次のように差が出ます。

```swift:使用例
print( 10 %   3) //  1
print( 10 %%  3) //  1

print( 10 %  -3) //  1
print( 10 %% -3) // -2

print(-10 %   3) // -1
print(-10 %%  3) //  2

print(-10 %  -3) // -1
print(-10 %% -3) // -1
```



# 3. 配列の末尾に追加する`+=`演算子

`array.append()`する演算子。タイプし易いので、使う頻度が高いです。

```swift
extension Array {
    @inlinable static func += (lhs: inout Self, rhs: Self.Element) { lhs.append(rhs) }
}
```

一応、使用例を書いておきます。

```swift:使用例
var array = Array<Int>()
for a in 1...10 {
    array += a
}
//array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```


# 4. 集合を操作する いくつかの 演算子

これも使う頻度が高い方です。
内容は、実装を見てもらえば 一目瞭然だと思います。


```swift
extension Set {
    @inlinable static func += (lhs: inout Self, rhs: Element) { lhs.insert(rhs) }
    @inlinable static func -= (lhs: inout Self, rhs: Element) { lhs.remove(rhs) }
    @inlinable static func += (lhs: inout Self, rhs: Self) { lhs.formUnion(rhs) }
    @inlinable static func -= (lhs: inout Self, rhs: Self) { lhs.subtract(rhs) }
    @inlinable static func + (lhs: Self, rhs: Self) -> Self { lhs.union(rhs) }
    @inlinable static func - (lhs: Self, rhs: Self) -> Self { lhs.subtracting(rhs) }
}
```

```swift:使用例
var set = Set<Int>()
for a in 1...10 {
    set += a
}
//set: [5, 6, 7, 9, 3, 4, 2, 10, 8, 1]

set -= Set(3...5)
//set: [9, 6, 7, 2, 10, 8, 1]

for s in set {
    set -= s
}
// set: []
```

# 5. ”含む？” `=~`演算子

## 5.1 範囲型 `=~`演算子


```swift
infix operator =~ : ComparisonPrecedence
@inlinable func =~ <T: FixedWidthInteger>(lhs: T, rhs: Range<T>) -> Bool { rhs ~= lhs }
@inlinable func =~ <T: FixedWidthInteger>(lhs: T, rhs: ClosedRange<T>) -> Bool { rhs ~= lhs }
```

右側の範囲の中に含むか? を判定します。
`if 0 <= x && x < 10` と等価ですが、変数`x`を2回書かなくて済むメリットがあります。
_（ Python だと `if 0 <= x < 10` と書けるのに近い？）_

```swift:使用例
let x = 8
if x =~ 0 ..< 10 { }  //then (true)
if x =~ 0 ... 7 { }   //else (false)
```

もともとは `if 0 ..< 10 ~= x { }` と書きます。
`if case 0 ..< 10 = x { }` とも書けます。

https://qiita.com/nak435/items/d6d9782d43c5e948447b

関数を使って、`if (0 ..< 10).contains(x) { }` とも書けます。



## 5.2 Sequence型 `=~`演算子

範囲型 `=~`演算子の流れで、今度は Collection に含むか? を判定します。


```swift
//infix operator =~ : ComparisonPrecedence
@inlinable func =~ <T: Collection> (lhs: T.Element, rhs: T) -> Bool where T.Element: Equatable { rhs.contains(lhs) }
```

主に集合型で使います。_Arrayで使うと$O(N)$です!!_

```swift:使用例
let set = Set([1, 3, 4, 6, 7, 9])
if 4 =~ set { }  //then (true)
if 8 =~ set { }  //else (false)
```


## 5.3 Dictionary型 `=~`演算子

Sequence型 `=~`演算子の流れで、今度は、Dictionary の`key`の存在チェックです。
しかし、これは推奨しません。理由は後述します。

```swift
extension Dictionary {
    @inlinable func contains(key: Key) -> Bool { self.keys.contains(key) }
    @inlinable static func =~ (lhs: Key, rhs: Self) -> Bool where Key: Hashable { rhs.contains(key: lhs) }
}
```


使い方

```swift:使用例
let dcit = ["A":0, "B":1, "C":2]
if "A" =~ dict { }  //then (true)
if "D" =~ dict { }  //else (false)
```

Dictionary型`key`の存在チェック`=~`演算子を推奨しない理由は、
Keyの存在チェックか、Valueの存在チェックか、`=~`演算子を見ただけでは（知らない人には）判断できないからです。

よって、次の関数を使うことをオススめします。

```swift
let dcit = ["A":0, "B":1, "C":2]
if dict.contains(key: "A") { }  //then (true)
if dict.contains(key: "D") { }  //else (false)
```

引数ラベルのおかげで、曖昧性が排除できますね。
（作者の自分は”知っているので”、普通に`=~`演算子を使います。タイプ数が”だんち”なので）

ちなみに、Dictionary の`Value`の存在チェックは準備していません。$O(N)$のため使わないからです。
もし、`Value`の存在チェックが必要なときは、`Value`を`key`にした別なDictionary変数か、`Value`を要素にしたSet変数を使い、こちらで存在チェックします。計算量が重要です。


# 6. 整数型floor演算子

↓　以前に公開済みです

https://qiita.com/nak435/items/fdfbab4cd7b75b5f260a#floor%E6%BC%94%E7%AE%97%E5%AD%90





# 愚痴

本当は、”含む？” `=~`演算子を`in`にしたかったのですが、Swiftは、演算子に 英数字 を使うことができませ。残念!!

https://qiita.com/nak435/items/49e5ea2c9cd947eed4de