こんにちは。TRILL iOSアプリを開発しているshira-shunです。
これはdelyアドベントカレンダー16日目の記事となります。
昨日は Yuya MasudaさんのバックエンドエンジニアからみたTRILLというプロダクトの魅力でした。
はじめに
Xcode13からApple製のパッケージをSwiftPMから手軽に使用できるようになりました。
どのApple製パッケージも使ったことがない私は、一番上に表示されていたswift-algorithmsに興味を持ちました。
swift-algorithms
の存在は以前から知っていましたが、パッケージ名がアルゴリズム
なのでアルゴリズムについて全く知識がない私にとっては縁のないものだと思っていました。
とりあえず、READMEを読んでみたら全然難しくなく、すぐ業務や個人開発でも使えるやんって思い少し触ってみました。
触った機能の中で今すぐにでも、取り入れられそうな機能を標準で書いたパターンとswift-algorithms
で書いたパターンを比べていくつか紹介したいと思います!!
nilが含まれる配列からnilを除外したい
before
let array = [1, nil, 2, nil, 3, nil, 4]
let safeArray = array.compactMap { $0 }
print(safeArray)
// [1, 2, 3, 4]
after
let array = [1, nil, 2, nil, 3, nil, 4]
let safeArray = array.compacted()
print(safeArray)
// [1, 2, 3, 4]
複数の値をランダムで取得したい
before
let array = 1 ... 10000
let randomElements = (0 ... 10).compactMap { _ in array.randomElement() } // 重複する可能性がある
print(randomElements)
// [9447, 5025, 4364, 2682, 9800, 31, 1450, 1694, 9268, 8418, 3718]
after
let array = 1 ... 10000
let randomElements = array.randomSample(count: 10) // 重複しない、取得件数が範囲より多い場合は範囲の分だけ取得する
print(randomElements)
// [1020, 8120, 634, 6403, 1735, 3809, 365, 4680, 7915, 4209]
// 順序も保証したい場合
let array = 1 ... 10000
let randomElements = array.randomStableSample(count: 10)
print(randomElements)
// [4846, 5317, 5388, 6455, 6971, 7493, 7533, 9096, 9282, 9533]
ユニークな配列を作成したい
before
let array = [99, 10, 13, 23, 13, 13, 19, 32, 43, 32, 10]
let unique = array.reduce([], { $0.contains($1) ? $0 : $0 + [$1] }).sorted()
print(unique)
// [10, 13, 19, 23, 32, 43, 99]
after
let array = [99, 10, 13, 23, 13, 13, 19, 32, 43, 32, 10]
let unique = array.uniqued().sorted()
print(unique)
// [10, 13, 19, 23, 32, 43, 99]
おまけ(頭文字でユニークかどうか判断する方法)
let animals = ["dog", "pig", "cat", "ox", "cow", "owl"]
let uniqued = animals.uniqued(on: { $0.first })
print(uniqued)
// ["dog", "pig", "cat", "ox"]
配列を結合したい
before
let array = Array(1 ... 5)
let result = array + array
print(result)
// [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
after
let array = 1 ... 5
let result = Array(chain(array, array))
print(result)
// [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
2つの配列を結合したい
let seasons = ["winter", "spring", "summer", "fall"]
for year in 2017...2020 {
for season in seasons {
print("\(year): \(season)")
}
}
// 2017: winter
// 2017: spring
// 2017: summer
// 2017: fall
// 2018: winter
// 2018: spring
// 2018: summer
// 2018: fall
// 2019: winter
// 2019: spring
// 2019: summer
// 2019: fall
// 2020: winter
// 2020: spring
// 2020: summer
// 2020: fall
after
let seasons = ["winter", "spring", "summer", "fall"]
for (year, season) in product(1900...2020, seasons) {
print("\(year): \(season)")
}
// 2017: winter
// 2017: spring
// 2017: summer
// 2017: fall
// 2018: winter
// 2018: spring
// 2018: summer
// 2018: fall
// 2019: winter
// 2019: spring
// 2019: summer
// 2019: fall
// 2020: winter
// 2020: spring
// 2020: summer
// 2020: fall
最小値、最大値を取得したい(複数個可能)
before
let numbers = [7, 1, 6, 2, 8, 3, 1, 9]
let smallestThree = numbers.sorted().prefix(3)
print(smallestThree)
// [1, 1, 2]
after
let numbers = [7, 1, 6, 2, 8, 3, 1, 9]
let smallestThree = numbers.min(count: 3, sortedBy: <)
print(smallestThree)
// [1, 1, 2]
nilを含む配列から最初の一件(nilではない)を取得したい
before
let array = [nil, 19090, nil, nil, 1323, nil]
let result = array.compactMap { $0 }.first
print(result)
// Optional(19090)
after
let array = [nil, 19090, nil, nil, 1323, nil]
let result = array.firstNonNil({ $0 })
print(result)
// Optional(19090)
感想
- READMEが充実しすぎて、難しすぎてよくわからないものがなかった。
- もっと早く出会いたかった...
-
compacted()
やuniqued()
は真っ先に取り入れても良いかなと思った。 - いくつかテストコードを書いてパフォーマンステストを行ってみたが、必ずしもswift-algorithmsの関数が早いわけではない
- 配列の個数が膨大だったり、明らかに処理が重そうなものに関しては明らかな性能差がでた。
- トリミングは実務案件で必ず出番がありそうな印象をもった。
どのアプリに導入しても損しないパッケージだった...
TRILLのチームにこれ導入してみないか?と相談して見ようと思います!
最後に
delyではエンジニア、デザイナー、PdMを積極採用しています。
少しでも興味がありましたら、お話だけでもできればと思います。