LoginSignup
3

More than 1 year has passed since last update.

swift-algorithmsを初めて触ってみた。

Posted at

こんにちは。TRILL iOSアプリを開発しているshira-shunです。
これはdelyアドベントカレンダー16日目の記事となります。

昨日は Yuya MasudaさんのバックエンドエンジニアからみたTRILLというプロダクトの魅力でした。

はじめに

Xcode13からApple製のパッケージをSwiftPMから手軽に使用できるようになりました。

image.png

どの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を積極採用しています。
少しでも興味がありましたら、お話だけでもできればと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3