そのフィールドの数を見ると、一つ一つに値を入れたくないな〜って思ってしまいますね。残念ながら、struct
を用いる限り一つ一つに入れるしかありません。
けど、Dictionary
を用いたら便利な書き方があります。まずは、その長いフィールド行をコピーして配列を作ります。
swift
1let keys = ["Group","FoodNumber","ListNumber","Tagnames","REFUSE","ENERC_KCAL","ENERC","WATER","PROTAIN","PROTCAA","FAT","FATNLEA","FASAT","FAMS","FAPU","CHOLE","CARBON","CHOAVLM","FIBSOL","FIBINS","FIBTG","ASH","NA","K","CA","MG","P","FE","ZN","CU","MN","ID","SE","CR","MO","RETOL","CARTA","CARTB","CRYPXB","CARTBEQ","VITA_RAE","VITD","TOCPHA","TOCPHB","TOCPHG","TOCPHD","VITK","THIAHCL","RIBF","NIA","VITB6A","VITB12","FOL","PANTAC","BIOT","VITC","NACL_EQ","ALC","NITRA ","THEBRN","CAFFN ","TAN","POLYPHENT","ACEAC","OIL","OA","CHANGEOFWAIT"]
配列にするのは、前後に["
と"]
をつけて、その1行だけにコンマ,
を検索して","
で書き換えます。空白がいくつかありますが削除していいです。
そうしたら、問題文の値の配列をvalues
で名付けて:
swift
1let values = ["01", "01001", "1", "アマランサス 玄穀 ", "0", "358", "1498", "13.5", "12.7", "(12.5)", "6.0", "5.0", "1.18", "1.48", "2.10", "(0)", "64.9", "63.5", "1.1", "6.3", "7.4", "2.9", "1", "600", "160", "270", "540", "9.4", "5.8", "0.92", "6.14", "1", "13", "7", "59", "(0)", "0", "2", "0", "2", "Tr", "(0)", "1.3", "2.3", "0.2", "0.7", "(0)", "0.04", "0.14", "1.0", "0.58", "(0)", "130", "1.69", "16.3", "(0)", "0", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"]
そしてkeys
とvalues
で簡単にDictionary
を作れます!
swift
1let food = Dictionary(uniqueKeysWithValues: zip(keys, values))
どうしてもstruct
を使わなければいけない場合は、コードを生成しましょう!REPL でコードを生成してコピーし、ソースにペーストしたいと思います。fuzzballさんのコードをテンプレートにして
swift
1struct Food {
2 var Group,FoodNumber,ListNumber,Tagnames,REFUSE,ENERC_KCAL,ENERC,WATER,PROTAIN,PROTCAA,FAT,FATNLEA,FASAT,FAMS,FAPU,CHOLE,CARBON,CHOAVLM,FIBSOL,FIBINS, FIBTG,ASH,NA,K,CA,MG,P,FE,ZN,CU,MN,ID,SE,CR,MO,RETOL,CARTA ,CARTB ,CRYPXB,CARTBEQ,VITA_RAE,VITD,TOCPHA,TOCPHB ,TOCPHG,TOCPHD,VITK,THIAHCL ,RIBF,NIA,VITB6A,VITB12,FOL,PANTAC,BIOT,VITC,NACL_EQ,ALC,NITRA ,THEBRN,CAFFN ,TAN,POLYPHENT,ACEAC,OIL,OA,CHANGEOFWAIT:String
3 init(withValues values: [String]) {
4 // 中身
5 // self.フィールド名 = values[i]
6 }
7}
まずはフィールド列を文字列にします:
swift
1var fieldList = "Group,FoodNumber,ListNumber,Tagnames,REFUSE,ENERC_KCAL,ENERC,WATER,PROTAIN,PROTCAA,FAT,FATNLEA,FASAT,FAMS,FAPU,CHOLE,CARBON,CHOAVLM,FIBSOL,FIBINS, FIBTG,ASH,NA,K,CA,MG,P,FE,ZN,CU,MN,ID,SE,CR,MO,RETOL,CARTA ,CARTB ,CRYPXB,CARTBEQ,VITA_RAE,VITD,TOCPHA,TOCPHB ,TOCPHG,TOCPHD,VITK,THIAHCL ,RIBF,NIA,VITB6A,VITB12,FOL,PANTAC,BIOT,VITC,NACL_EQ,ALC,NITRA ,THEBRN,CAFFN ,TAN,POLYPHENT,ACEAC,OIL,OA,CHANGEOFWAIT"
空白を抜きおいて:
swift
1fieldList.removeAll(where: { $0.isWhitespace })
フィールド名配列をsplit
で作ります:
swift
1let fieldNames = fieldList.split(separator: ",")
そうしたら、init(withValues: [String])
の中身を生成します:
swift
1for (index, name) in fieldNames.enumerated() {
2 print("self.(name) = values[(index)]")
3}
結果は下記の通りです。是非お試してみてください。
swift
1self.Group = values[0]
2self.FoodNumber = values[1]
3self.ListNumber = values[2]
4self.Tagnames = values[3]
5self.REFUSE = values[4]
6self.ENERC_KCAL = values[5]
7self.ENERC = values[6]
8self.WATER = values[7]
9self.PROTAIN = values[8]
10self.PROTCAA = values[9]
11self.FAT = values[10]
12self.FATNLEA = values[11]
13self.FASAT = values[12]
14self.FAMS = values[13]
15self.FAPU = values[14]
16self.CHOLE = values[15]
17self.CARBON = values[16]
18self.CHOAVLM = values[17]
19self.FIBSOL = values[18]
20self.FIBINS = values[19]
21self.FIBTG = values[20]
22self.ASH = values[21]
23self.NA = values[22]
24self.K = values[23]
25self.CA = values[24]
26self.MG = values[25]
27self.P = values[26]
28self.FE = values[27]
29self.ZN = values[28]
30self.CU = values[29]
31self.MN = values[30]
32self.ID = values[31]
33self.SE = values[32]
34self.CR = values[33]
35self.MO = values[34]
36self.RETOL = values[35]
37self.CARTA = values[36]
38self.CARTB = values[37]
39self.CRYPXB = values[38]
40self.CARTBEQ = values[39]
41self.VITA_RAE = values[40]
42self.VITD = values[41]
43self.TOCPHA = values[42]
44self.TOCPHB = values[43]
45self.TOCPHG = values[44]
46self.TOCPHD = values[45]
47self.VITK = values[46]
48self.THIAHCL = values[47]
49self.RIBF = values[48]
50self.NIA = values[49]
51self.VITB6A = values[50]
52self.VITB12 = values[51]
53self.FOL = values[52]
54self.PANTAC = values[53]
55self.BIOT = values[54]
56self.VITC = values[55]
57self.NACL_EQ = values[56]
58self.ALC = values[57]
59self.NITRA = values[58]
60self.THEBRN = values[59]
61self.CAFFN = values[60]
62self.TAN = values[61]
63self.POLYPHENT = values[62]
64self.ACEAC = values[63]
65self.OIL = values[64]
66self.OA = values[65]
67self.CHANGEOFWAIT = values[66]
追記:fuzzballさんがリフレクションの使い方を教えてくれました!ありがとうございます!
swift
1struct Food { var Group, FoodNumber, (中略) : String? } //一時的にオプショナル型にする
2
3Mirror(reflecting: Food()).children.compactMap { $0.label }.enumerated().forEach {
4 print("self.($0.element) = values[($0.offset)]")
5}
struct Food
の中のvar
の型が元はString
ですが、Food()
を使えるようになるため、String?
みたいに?
で後飾ってオプショナル型にします。
compactMap
とforEach
が実にいいことで覚えるのをおすすめですが、for loopで書いたらこうなります:
swift
1for (offset, (label, _)) Mirror(reflecting: Food()).children.enumerated() {
2 print("self.(label) = values[(offset)]")
3}
出力は上記と同じになります。