Я работаю над некоторым кодом и получил неверный вывод и пытался его решить, я знаю, что это довольно простое исправление (или, по крайней мере, должно быть), возможно, правильное его преобразование или обработка. Тем не менее, у меня было несколько попыток без успеха.
Вот код в Swift Playground
import UIKit
import Foundation
// MARK:- Declarations
// The varible defintions including the expected unique key values, the associated data and the dictionary which will be returned
var arrayOfUniqueFieldNames = ["value1", "value2", "value3"]
var dictionaryOfKeyPairedData : [Int: [String]] = [
0: ["value1", "a"],
1: ["value2", "b"],
2: ["value3", "c"],
3: ["value1", "x"],
4: ["value2", "y"],
5: ["value3", "z"]]
var dictionaryOfDatasets = [String: Any]()
// MARK:- Code Body
// Iterates through the dictionaryOfKeyPairedData assigning each key if it doesn't exist to the array to print and the value to the existing key, each key has mutliple values stored as an array
for counterOne in 0...dictionaryOfKeyPairedData.count-1{
// gets the current key value from the dictionary as a String
let currentKeyValue = returnKeyofDictionaryArray(theDictionaryInQuestion: dictionaryOfKeyPairedData, indexToLookUp: counterOne, value: 0)
// gets the current value from the dictionary as a String as it associates with the current key
let currentValuePair = returnKeyofDictionaryArray(theDictionaryInQuestion: dictionaryOfKeyPairedData, indexToLookUp: counterOne, value: 1)
// Fetches the array from the dictionary so it can be manipulated
var existingItems = Array(arrayLiteral: dictionaryOfDatasets[currentKeyValue]) //Where I believe the Optional is not handled correctly
// If the key doesn't exist it saves the value as the key to the key, if it does exist it saves the value to the value as a value
if existingItems[0] == nil{
existingItems = [currentValuePair] //Where I believe the extranious brackets are getting added
}else{
existingItems.append(currentValuePair)
}
// resaves the manipulated array alongside the existing key
dictionaryOfDatasets[currentKeyValue] = existingItems
}
// prints the data - OUTPUT
print(dictionaryOfDatasets)
// MARK:- Functions
// Returns the key for the value for the prescribed array
func returnKeyofDictionaryArray(theDictionaryInQuestion: [Int: [String]], indexToLookUp: Int, value: Int) -> String{
return theDictionaryInQuestion[indexToLookUp]![value]
}
Ожидаемый результат
["value2": ["b", "y"], "value1": ["a", "x"], "value3": ["c","z"]]
или
["value1": ["a", "x"], "value2": ["b", "y"], "value3": ["c","z"]]
Фактический результат
["value1": [Optional([Optional("a")]), Optional("x")], "value2": [Optional([Optional("b")]), Optional("y")], "value3": [Optional([Optional("c")]), Optional("z")]]
Поскольку есть дублирующиеся «ключи», необходима нумерация.
К вашему сведению, и KeyValuePairs
, и [(String, String)]
допускают дублирование ключей.
Вы используете Any
в качестве типа значения выходного словаря, в то время как это может быть просто массив String
s. И использование Array(arrayLiteral: dictionaryOfDatasets[currentKeyValue])
не помогает.
Вы можете получить желаемый результат, перебирая исходный словарь и сохраняя значения непосредственно в новом, без вспомогательной функции, такой как returnKeyofDictionaryArray
.
Вот как вы можете этого добиться:
// The variable defintions including the expected unique key values, the associated data and the dictionary which will be returned
var arrayOfUniqueFieldNames = ["value1", "value2", "value3"]
var dictionaryOfKeyPairedData : [Int: [String]] = [
0: ["value1", "a"],
1: ["value2", "b"],
2: ["value3", "c"],
3: ["value1", "x"],
4: ["value2", "y"],
5: ["value3", "z"]]
// This is a dictionary of String to String-arrays
var dictionaryOfDatasets = [String: [String]]()
// MARK:- Code Body
// Just iterate through the values of the dictionary, given that
// you are not interested in the Int keys
dictionaryOfKeyPairedData.values.forEach {
if dictionaryOfDatasets[$0[0]] == nil {
dictionaryOfDatasets[$0[0]] = [$0[1]]
} else {
dictionaryOfDatasets[$0[0]]?.append($0[1])
}
}
// Sorting, if you need:
// Here is where you sort the arrays inside each value of the dictionary
dictionaryOfDatasets.keys.forEach {
dictionaryOfDatasets[$0] = dictionaryOfDatasets[$0]?.sorted(by: { $0 < $1 })
}
// prints the data - OUTPUT
print(dictionaryOfDatasets) // ["value3": ["c", "z"], "value2": ["b", "y"], "value1": ["a", "x"]]
Вы, сначала вам нужно изменить Dictioanry
ключ Any
на String
И вы можете добиться ожидаемого результата более элегантным способом.
var arrayOfUniqueFieldNames = ["value1", "value2", "value3"]
var dictionaryOfKeyPairedData : [Int: [String]] = [
0: ["value1", "a"],
1: ["value2", "b"],
2: ["value3", "c"],
3: ["value1", "x"],
4: ["value2", "y"],
5: ["value3", "z"]]
var dictionaryOfDatasets = [String: [String]]()
arrayOfUniqueFieldNames.forEach{
let key = $0
dictionaryOfKeyPairedData.filter({$0.value.first == key}).forEach{
if dictionaryOfDatasets[key] != nil {
var val = dictionaryOfDatasets[key]
val?.append($0.value.last ?? "")
dictionaryOfDatasets[key] = val
}else{
dictionaryOfDatasets[key] = [$0.value.last ?? ""]
}
}
}
print(dictionaryOfDatasets)
OUTPUT:
["value1": ["a", "x"], "value3": ["z", "c"], "value2": ["y", "b"]]
Почему ваши входные данные в таком формате, которым так неудобно манипулировать? Цифры в качестве ключей кажутся совершенно ненужными. Как насчет того, чтобы просто хранить строки в коллекции
KeyValuePairs
или, по крайней мере,[(String, String)]
? Цифровые клавиши вообще что-нибудь означают?