辞書の値がコレクション型であるかどうかを検査するために実行時イントロスペクションを使用することができます。子要素(配列の場合は要素)を反復処理し、実際の配列Any
に追加します。 Swiftにあなたの辞書のAny
の値が実際にはの配列であることを知らせます。
/* Example setup */
struct A {
var x: Int
init(_ x: Int) { self.x = x }
}
struct B {
var y: Int
init(_ y: Int) { self.y = y }
}
var c: [String:Any] = [
"a": [A(1), A(2)],
"b": [B(3)],
"c": "JustAString",
"d": A(0)
]
など。あるいは
/* runtime introspection to extract array values from dictionary */
var commonAnyArr: [[Any]] = []
for (_, value) in c {
if case let m = Mirror(reflecting: value)
where (m.displayStyle ?? .Struct) == .Collection {
let arr = m.children.map { $0.value }
commonAnyArr.append(arr)
}
}
/* resulting array of any arrs, that Swift now recognize as actual arrays */
commonAnyArr.forEach { print($0) }
/* [B(y: 3)]
[A(x: 1), A(x: 2)] */
commonAnyArr.flatten().forEach { print($0) }
/* B(y: 3)
A(x: 1)
A(x: 2) */
を以下のように、(ただし新しい辞書にAny
値によって包まれ、基礎となる値は、実際にはアレイであるc
の唯一のキーと値のペアを含む、新たな辞書を構築するために、実行時イントロスペクションを使用し値がAny
の配列であることを明示的に指定します)。
/* runtime introspection to extract array values from dictionary */
var dictOfAnyArrs: [String: [Any]] = [:]
for (key, value) in c {
if case let m = Mirror(reflecting: value)
where (m.displayStyle ?? .Struct) == .Collection {
let arr = m.children.map { $0.value }
dictOfAnyArrs[key] = arr
}
}
/* "remaining" dictionary keys now only with [Arr] values */
for (key, arr) in dictOfAnyArrs {
for element in arr {
print("Do something with element \(element)")
}
print("---")
}
/* Do something with element B(y: 3)
---
Do something with element A(x: 1)
Do something with element A(x: 2)
--- */
だけではなく、技術的な側面のうち、より上記(スウィフトの目と静的型付けとランタイムの安全性におけるその誇りで)やや「ハック」と考えることができ、そしておそらくほとんどが面白いことに注意してください実際の生産コードで使用されるよりも(私は個人的には自分自身の生産で上記のようなものを許可しません)。おそらく、あなたが一歩踏み出してこの問題にどのように遭遇したかを見てみると、コードを再作成して、ランタイムハッキングに頼る必要がないように設計することができます。
私は本当にあなたのデータ構造があなたがこのようなことをしようとしているように見えるかを知りたいのです。これは[XY問題](http://meta.stackexchange.com/q/66377/244435)のように聞こえます。 – nhgrif