LoginSignup
5
5

More than 5 years have passed since last update.

swiftで [Int?] な配列を [Int]? にするのはどうするのが良いのだろうか

Last updated at Posted at 2015-06-16

オプショナルな値の配列を配列のオプショナルに変えたいことはよくある。(たぶん)
[Int?][Int]? にしたい。

Haskellを例にだす。

[Just 1, Just 2, Nothing, Just 3] :: [Maybe Int]
sequence [Just 1, Just 2, Nothing, Just 3] :: Maybe [Int] -- => Nothing
sequence [Just 1, Just 2, Just 3] :: Maybe [Int]  -- => Just [1,2,3]

ひとつでもNothingがあればNothingになる。

Optinalに限定にしているので、こんな風に書いておいた。

func sequence<T>(xs: [T?]) -> [T]? {
    var result: [T]? = []
    for optX in xs {
        if let x = optX {
            result?.append(x)
        } else {
            return nil
        }
    }
    return result
}

let xs: [Int?] = [1, 2, nil, 3] // => [{Some 1}, {Some 2}, nil, {Some 3}]
sequence(xs)  // => nil
let ys: [Int?] = [1,2,3] // => [{Some 1}, {Some 2}, {Some 3}]
sequence(ys) // => [1, 2, 3]

内部に副作用がある場合は途中でreturnすべきでない気がする。

一応 reduceでもかいておこう。

func sequence2<T>(xs: [T?]) -> [T]? {
    return xs.reduce([], combine: { (var acc,optX) in
        if let x = optX {
            acc?.append(x)
            return acc
        } else {
            return nil
        }
    })
}
sequence2([1, 2, nil, 3])
sequence2([1,2,3])

accに変更を加えないといけないのでvarにした。このあたりどうかいていくのがいいのかよくわからない。

より良い方法やライブラリがあったら教えて欲しい。

実際のsequenceはもっと一般的なので注意.

> :t sequence
sequence :: (Monad m, Traversable t) => t (m a) -> m (t a)
5
5
4

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
  3. You can use dark theme
What you can do with signing up
5
5