この記事について
【Swift】配列の配列について詳しく。 - Qiitaで「配列の配列」についてまとめたのですが、Swift3で変更点が多くあったので別記事にしました。
joined
split
flatMap
joined
flatten
がなくなりjoined
になりました。
配列の要素がString
のとき
extension Array where Element == String {
/// Returns a new string by concatenating the elements of the sequence,
/// adding the given separator between each element.
///
/// The following example shows how an array of strings can be joined to a
/// single, comma-separated string:
///
/// let cast = ["Vivien", "Marlon", "Kim", "Karl"]
/// let list = cast.joined(separator: ", ")
/// print(list)
/// // Prints "Vivien, Marlon, Kim, Karl"
///
/// - Parameter separator: A string to insert between each of the elements
/// in this sequence. The default separator is an empty string.
/// - Returns: A single, concatenated string.
public func joined(separator: String = default) -> String
}
使い方
let cast = ["Vivien", "Marlon", "Kim", "Karl"]
let list = cast.joined(separator: ", ")
print(list)
// "Vivien, Marlon, Kim, Karl"
単に結合するだけのときは引数なしでOK
let aiu = ["あ", "い", "う"]
let list = aiu.joined()
print(list)
// "あいう"
配列の配列のとき
extension Array where Element : Collection {
/// Returns the elements of this collection of collections, concatenated.
///
/// In this example, an array of three ranges is flattened so that the
/// elements of each range can be iterated in turn.
///
/// let ranges = [0..<3, 8..<10, 15..<17]
///
/// // A for-in loop over 'ranges' accesses each range:
/// for range in ranges {
/// print(range)
/// }
/// // Prints "0..<3"
/// // Prints "8..<10"
/// // Prints "15..<17"
///
/// // Use 'joined()' to access each element of each range:
/// for index in ranges.joined() {
/// print(index, terminator: " ")
/// }
/// // Prints: "0 1 2 8 9 15 16"
///
/// - Returns: A flattened view of the elements of this
/// collection of collections.
///
/// - SeeAlso: `flatMap(_:)`, `joined(separator:)`
public func joined() -> FlattenCollection<Array<Element>>
}
/// Returns the concatenated elements of this sequence of sequences,
/// inserting the given separator between each element.
///
/// This example shows how an array of `[Int]` instances can be joined, using
/// another `[Int]` instance as the separator:
///
/// let nestedNumbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
/// let joined = nestedNumbers.joined(separator: [-1, -2])
/// print(Array(joined))
/// // Prints "[1, 2, 3, -1, -2, 4, 5, 6, -1, -2, 7, 8, 9]"
///
/// - Parameter separator: A sequence to insert between each of this
/// sequence's elements.
/// - Returns: The joined sequence of elements.
///
/// - SeeAlso: `joined()`
public func joined<Separator : Sequence where Separator.Iterator.Element == Iterator.Element.Iterator.Element>(separator: Separator) -> JoinedSequence<Array<Element>>
使い方
単に結合するとき → flatMap
let arrayOfArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(arrayOfArray.joined().map { $0 })
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(Array(arrayOfArray.joined()))
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
入れ子の配列間になにか挟み込みたい場合はseparator
を配列で指定する
let arrayOfArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(arrayOfArray.joined(separator: [-1, -2]).map { $0 })
// [1, 2, 3, -1, -2, 4, 5, 6, -1, -2, 7, 8, 9]
print(Array(arrayOfArray.joined(separator: [-1, -2])))
// [1, 2, 3, -1, -2, 4, 5, 6, -1, -2, 7, 8, 9]
Python
のjoin
のように使いたければ
extension String {
func join (_ seq: [String]) -> String {
return seq.joined(separator: self)
}
}
と宣言して、以下のように使えます。
let strArray = ["foo", "bar", "buz"]
"".join(strArray)
// "foobarbuz"
split
- 要素で指定
/// Returns the longest possible subsequences of the collection, in order,
/// around elements equal to the given element.
///
/// The resulting array consists of at most `maxSplits + 1` subsequences.
/// Elements that are used to split the collection are not returned as part
/// of any subsequence.
///
/// The following examples show the effects of the `maxSplits` and
/// `omittingEmptySubsequences` parameters when splitting a string at each
/// space character (" "). The first use of `split` returns each word that
/// was originally separated by one or more spaces.
///
/// let line = "BLANCHE: I don't want realism. I want magic!"
/// print(line.characters.split(separator: " ")
/// .map(String.init))
/// // Prints "["BLANCHE:", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"
///
/// The second example passes `1` for the `maxSplits` parameter, so the
/// original string is split just once, into two new strings.
///
/// print(line.characters.split(separator: " ", maxSplits: 1)
/// .map(String.init))
/// // Prints "["BLANCHE:", " I don\'t want realism. I want magic!"]"
///
/// The final example passes `false` for the `omittingEmptySubsequences`
/// parameter, so the returned array contains empty strings where spaces
/// were repeated.
///
/// print(line.characters.split(separator: " ", omittingEmptySubsequences: false)
/// .map(String.init))
/// // Prints "["BLANCHE:", "", "", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"
///
/// - Parameters:
/// - separator: The element that should be split upon.
/// - maxSplits: The maximum number of times to split the collection, or
/// one less than the number of subsequences to return. If
/// `maxSplits + 1` subsequences are returned, the last one is a suffix
/// of the original collection containing the remaining elements.
/// `maxSplits` must be greater than or equal to zero. The default value
/// is `Int.max`.
/// - omittingEmptySubsequences: If `false`, an empty subsequence is
/// returned in the result for each consecutive pair of `separator`
/// elements in the collection and for each instance of `separator` at
/// the start or end of the collection. If `true`, only nonempty
/// subsequences are returned. The default value is `true`.
/// - Returns: An array of subsequences, split from this collection's
/// elements.
public func split(separator: Element, maxSplits: Int = default, omittingEmptySubsequences: Bool = default) -> [ArraySlice<Element>]
- 条件で指定
/// Returns the longest possible subsequences of the collection, in order,
/// that don't contain elements satisfying the given predicate.
///
/// The resulting array consists of at most `maxSplits + 1` subsequences.
/// Elements that are used to split the sequence are not returned as part of
/// any subsequence.
///
/// The following examples show the effects of the `maxSplits` and
/// `omittingEmptySubsequences` parameters when splitting a string using a
/// closure that matches spaces. The first use of `split` returns each word
/// that was originally separated by one or more spaces.
///
/// let line = "BLANCHE: I don't want realism. I want magic!"
/// print(line.characters.split(whereSeparator: { $0 == " " })
/// .map(String.init))
/// // Prints "["BLANCHE:", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"
///
/// The second example passes `1` for the `maxSplits` parameter, so the
/// original string is split just once, into two new strings.
///
/// print(
/// line.characters.split(
/// maxSplits: 1, whereSeparator: { $0 == " " }
/// ).map(String.init))
/// // Prints "["BLANCHE:", " I don\'t want realism. I want magic!"]"
///
/// The final example passes `false` for the `omittingEmptySubsequences`
/// parameter, so the returned array contains empty strings where spaces
/// were repeated.
///
/// print(line.characters.split(omittingEmptySubsequences: false, whereSeparator: { $0 == " " })
/// .map(String.init))
/// // Prints "["BLANCHE:", "", "", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"
///
/// - Parameters:
/// - maxSplits: The maximum number of times to split the collection, or
/// one less than the number of subsequences to return. If
/// `maxSplits + 1` subsequences are returned, the last one is a suffix
/// of the original collection containing the remaining elements.
/// `maxSplits` must be greater than or equal to zero. The default value
/// is `Int.max`.
/// - omittingEmptySubsequences: If `false`, an empty subsequence is
/// returned in the result for each pair of consecutive elements
/// satisfying the `isSeparator` predicate and for each element at the
/// start or end of the collection satisfying the `isSeparator`
/// predicate. The default value is `true`.
/// - isSeparator: A closure that takes an element as an argument and
/// returns a Boolean value indicating whether the collection should be
/// split at that element.
/// - Returns: An array of subsequences, split from this collection's
/// elements.
public func split(maxSplits: Int = default, omittingEmptySubsequences: Bool = default, whereSeparator isSeparator: (Element) throws -> Bool) rethrows -> [ArraySlice<Element>]
使い方
let array = [7, 2, 1, 2, 1, 1, 3, 2, 3, 4, 1, 5]
// 空の配列を許容しない
print(array.split(separator: 1).map { [Int]($0) })
// [[7, 2], [2], [3, 2, 3, 4], [5]]
// 空の配列を許容する
print(array.split(separator: 1, omittingEmptySubsequences: false).map { [Int]($0) })
// [[7, 2], [2], [], [3, 2, 3, 4], [5]]
// 偶数の要素で分割(条件指定)
print(array.split { $0 % 2 == 0 }.map { [Int]($0) })
// [[7], [1], [1, 1, 3], [3], [1, 5]]
// コンマで分割
let line = "hoge,piyo,foo,baa"
print(line.characters.split { $0 == "," }.map(String.init))
// ["hoge", "piyo", "foo", "baa"]
flatMap
/// Returns an array containing the concatenated results of calling the
/// given transformation with each element of this sequence.
///
/// Use this method to receive a single-level collection when your
/// transformation produces a sequence or collection for each element.
///
/// In this example, note the difference in the result of using `map` and
/// `flatMap` with a transformation that returns an array.
///
/// let numbers = [1, 2, 3, 4]
///
/// let mapped = numbers.map { Array(count: $0, repeatedValue: $0) }
/// // [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
///
/// let flatMapped = numbers.flatMap { Array(count: $0, repeatedValue: $0) }
/// // [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
///
/// In fact, `s.flatMap(transform)` is equivalent to
/// `Array(s.map(transform).joined())`.
///
/// - Parameter transform: A closure that accepts an element of this
/// sequence as its argument and returns a sequence or collection.
/// - Returns: The resulting flattened array.
///
/// - Complexity: O(*m* + *n*), where *m* is the length of this sequence
/// and *n* is the length of the result.
/// - SeeAlso: `joined()`, `map(_:)`
public func flatMap<SegmentOfResult : Sequence>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Iterator.Element]
(参考)
/// Returns an array containing the non-`nil` results of calling the given
/// transformation with each element of this sequence.
///
/// Use this method to receive an array of nonoptional values when your
/// transformation produces an optional value.
///
/// In this example, note the difference in the result of using `map` and
/// `flatMap` with a transformation that returns an optional `Int` value.
///
/// let possibleNumbers = ["1", "2", "three", "///4///", "5"]
///
/// let mapped: [Int?] = numbers.map { str in Int(str) }
/// // [1, 2, nil, nil, 5]
///
/// let flatMapped: [Int] = numbers.flatMap { str in Int(str) }
/// // [1, 2, 5]
///
/// - Parameter transform: A closure that accepts an element of this
/// sequence as its argument and returns an optional value.
/// - Returns: An array of the non-`nil` results of calling `transform`
/// with each element of the sequence.
///
/// - Complexity: O(*m* + *n*), where *m* is the length of this sequence
/// and *n* is the length of the result.
public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
使い方
// 結合
let arrayOfArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(arrayOfArray.flatMap { $0 })
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 1の削除
let array = [7, 2, 1, 2, 1, 1, 3, 2, 3, 4, 1, 5]
print(array.split(separator: 1).flatMap { $0 })
// [7, 2, 2, 3, 2, 3, 4, 5]
-
map
とflatMap
の挙動の違い
let numbers = [1, 2, 3, 4]
let mapped = numbers.map { Array(repeating: $0, count: $0) }
print(mapped)
// [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
let flatMapped = numbers.flatMap { Array(repeating: $0, count: $0) }
print(flatMapped)
// [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]