web-dev-qa-db-ja.com

Swift 2.2(3.0)のオブジェクトのマップ変更配列

各要素をループせずに、フライのSwift)でmapを使用してオブジェクトの配列を変更できるようにしたい。

ここまではこのようなことができました(詳細は ここ

gnomes = gnomes.map { (var gnome: Gnome) -> Gnome in
    gnome.age = 140
    return gnome
}

Erica Sadunと他の人たちのおかげで、新しい提案が通過し、Cスタイルのループを取り除き、ループ内でvarを使用するようになりました。

私の場合、最初にvarを削除するように警告が表示され、次にエラーが発生します。私のgnomeは定数です(当然)

私の質問は次のとおりです。map内の配列、またはSwift 3.0)に完全に備えるために、新しいスタイルのループを変更するにはどうすればよいですか?

11
kernelpanic

その構文を維持したい場合は、(可変の)一時変数を使用してください

gnomes = gnomes.map { (gnome: Gnome) -> Gnome in
  var mutableGnome = gnome
  mutableGnome.age = 140
  return mutableGnome
}
24
vadian

(以下は、Gnomeが参照型である場合に続きます;クラス-Gnomeをどのように定義したかを示していないためです。ここで、値型(構造体)としてのGnome、@ vadian:sの回答を参照)


varの削除は、.mapを使用してreferenceの配列のmutableメンバーを変更しても効果がありません。 )オブジェクトを入力します。つまり、古いアプローチを使用するだけで済みます(ただし、.mapクロージャー署名のvarは省略します)。

class Gnome {
    var age = 42
}

var gnomes = [Gnome(), Gnome(), Gnome()]

gnomes = gnomes.map {
    $0.age = 150
    return $0
}

/* result */
gnomes.forEach { print($0.age) } // 3x 150

ただし、.mapの結果を新しい配列に割り当てるのではなく、元の配列を変更するだけの場合は、.forEachよりも.mapの方が適切な選択となる可能性があります。

gnomes.forEach { $0.age = 140 }

/* result */
gnomes.forEach { print($0.age) } // 3x 140
14
dfri

与えられた:

struct Gnome {
    var age: Int = 0
}

var gnomes = Array(count: 5, repeatedValue: Gnome())

... 2つのまともなオプションがあります。 1つ目は、@ vadianが言ったとおりです。

gnomes = gnomes.map{
    var gnome = $0
    gnome.age = 70
    return gnome
}

2つ目は、「エージング」privateを制御し続け、呼び出しポイントでのマッピングを簡素化します。

struct Gnome {
    private(set) var age: Int = 0

    func aged(age: Int) -> Gnome {
        var gnome = self
        gnome.age = age
        // any other ageing related changes
        return gnome
    }
}

gnomes = gnomes.map{ $0.aged(140) }

もちろん、参照型はまだプログラミングでの位置を占めており、この場合はより適している可能性があります。ここで発生している摩擦は、これらの構造をオブジェクトであるかのように処理しようとしていることを示しています。それが必要な動作である場合は、Gnomeclassとして実装することを検討する必要があります。

1
milos