2017-11-15 2 views
-2

私はSwiftに非常に単純な問題があります。 私は、この関数を作成:下付き文字で代入できません: 'dict'は 'let'定数です

var dictAges : [String: Int] = ["John":40, "Michael":20, "Bob": -16] 

func correctAges(dict:[String:Int]) { 
    for (name, age) in dict { 
      guard age >= 0 else { 
      dict[name] = 0 
      continue 
      } 
    } 
} 
correctAges(dict:dictAges) 

をしかし、私はエラーを理解していない:

"cannot assign through subscript: 'dict' is a 'let' constant, dict[name] = 0"

私はそれを解決できますか?

+2

https://stackoverflow.com/a/36165146/5496433 – BallpointBen

+3

Swiftを学習してみませんか? – matt

+0

無関係ですが、私はここで 'ガード'を使用しません - 単純な 'if'で十分です。あるいは、ループの 'where'節でさえ:' age(0、... {{} {{}} 'の '(name、age)'のために。 – Hamish

答えて

2

関数の入力引数は関数本体の中では変更できません。ディクショナリは値型なので、関数内に表示されるdictは実際には元のdictAgesのコピーです。値の型を入力引数として持つ関数を呼び出すと、その入力引数は参照渡しではなく値渡しとなり、元の変数にはアクセスできなくなります。

入力引数をinoutと宣言するか、より機能的なアプローチを希望する場合は、関数から辞書の変形バージョンを返します。

機能アプローチ:

var dictAges : [String: Int] = ["John":40, "Michael":20, "Bob": -16] 

func correctAges(dict:[String:Int])->[String:Int] { 
    var mutatedDict = dict 
    for (name, age) in mutatedDict { 
      guard age >= 0 else { 
       mutatedDict[name] = 0 
       continue 
      } 
    } 
    return mutatedDict 
} 
let newDict = correctAges(dict:dictAges) //["Michael": 20, "Bob": 0, "John": 40] 

INOUTバージョン:あなたが関数に渡された辞書を変異させることができ

func correctAges(dict: inout [String:Int]){ 
    for (name,age) in dict { 
     guard age >= 0 else { 
      dict[name] = 0 
      continue 
     } 
    } 
} 

correctAges(dict: &dictAges) //["Michael": 20, "Bob": 0, "John": 40] 
+4

' inout'を使わないでください。関数は、理由のために戻り値を持ちます。 – rmaddy

+1

スウィフトで黄金のルールがあります:答えは 'inout'を使用している_ifが、私は同意する@rmaddy – holex

+0

は、戻り値を持つバージョンが好ましい間違っquestion_を上げたが、私はOPの両方のバージョンを見せたかったです。 –

0

あなたの期待はスウィフトで辞書がAであるという単純な理由のため、間違っています値のタイプ。辞書内の型、StringとIntも値です。実際には、パラメータdictは、dictAgesコピーです。あなたがdictに行ったことは、dictAgesには何の影響も与えません。

これは、アーキテクチャ全体を再考する必要がある兆候です。年齢として負の数を入力するのが間違っていた場合、それが入力されていたときにその前をつかんだはずです。実際には、モデルのInts辞書全体をここではおそらく間違っています。あなたはPersonの辞書を使いました。ここでPersonは構造体でageで、ageが最初に否定的になるのを防ぐセッターがあります。一般的に

var dictAges : [String: Int] = ["John":40, "Michael":20, "Bob": -16] 

extension Dictionary where Value : SignedInteger { 
    mutating func fixAges() { 
     for (k,v) in self { 
      if v < 0 { 
       self[k] = 0 
      } 
     } 
    } 
} 

dictAges.fixAges() 
0

、それが変異するのはよくないです:あなたはは、任意の辞書を通ると非負する値を修正する機能を持っている必要があり、辞書そのものの機能があること作る場合

あなたがそれをループしているときに、あなたのコード内の辞書の不変なコピーを取得するだけです。

スウィフト4

私はよりよいアプローチはmapを使用すると、より機能的なアプローチを取ることができると思います:

var dictAges : [String: Int] = ["John":40, "Michael":20, "Bob": -16] 

func correctAges(dict:[String:Int]) -> [String:Int] 
{ 
    let corrected = dict.map { (name, age) in age > 0 ? (name, age) : (name, 0) } 
    return Dictionary(uniqueKeysWithValues: corrected) 
} 

dictAges = correctAges(dict: dictAges) 
print(dictAges) // ["Michael": 20, "Bob": 0, "John": 40] 

[String:Int]辞書のために、このメソッドを再利用することができますこの方法を。

関連する問題