2016-11-24 5 views
0

Ich bin neu in Swift und Programmierung im Allgemeinen. Ich habe folgende dictionary erklärt:Wie Zugriff auf Inhalte eines Wörterbuchs mit String als Schlüssel und Arrays von Any als Werte?

let fruits: [String:[[Any]]] = [ 
    "Apple": [ 
     ["Gravenstein",122,100], 
     ["Ginger Gold", 119, 130], 
     ["Jazz", 150, 190] 

    ], 

    "Grapes": [ 
     ["Cabernet Sauvignon",120,100], 
     ["Merlot", 150, 130], 
     ["Tempranillo", 130, 190] 

    ] 
] 

Ich möchte nun eine Funktion programmieren, dass basierend auf 2 Variablen, sagen wir, var selectedFruit = "Apple" und var selectedVariety = "Ginger Gold". Basierend auf diesen 2 Variablen sollte ich in der Lage sein, die erste Zahl (122) zu erhalten und sie zu der zweiten Zahl (100) hinzuzufügen. Ich habe versucht, Karte und Flatmap ohne Erfolg. Irgendeine Hilfe ?

+0

uns zeigen, was haben Sie bisher versucht, bitte. – dirtydanee

+0

Ich habe gedruckt (fruits.map {$ 0.key == selectedFruit}), die ein Array [True, False] zurückgibt, aber hier bleibe ich stecken .... – fbelfort

Antwort

2

So etwas wird Ihr dort:

let selectedFruit = "Apple" 
let selectedVariety = "Ginger Gold" 

if let arrays = fruits[selectedFruit] { 
    for array in arrays { 
     if let first = array.first as? String, first == selectedVariety { 
      if let num1 = array[1] as? Int, let num2 = array[2] as? Int { 
       print(num1 + num2) 
      } 
     } 
    } 
} 

Aber Sie haben mit ziemlicher Sicherheit die falsche Struktur für Ihre Daten ausgewählt. Wenn Sie sich selbst mit Any finden, gibt es eine bessere Lösung.

Am einfachsten wäre es, Wörterbücher zu verschachteln, bei denen Ihre Früchte und Sorten die Schlüssel sind.

let fruits: [String: [String: [Int]]] = [ 
    "Apple": [ 
     "Gravenstein": [122, 100], 
     "Ginger Gold": [119, 130], 
     "Jazz": [150, 190] 
    ], 

    "Grapes": [ 
     "Cabernet Sauvignon": [120, 100], 
     "Merlot": [150, 130], 
     "Tempranillo": [130, 190] 
    ] 
] 

if let values = fruits[selectedFruit]?[selectedVariety] { 
    print(values[0] + values[1]) 
} 
+0

Danke für die Antwort. Die neue Struktur ist also ein Wörterbuch mit einem String als Schlüssel und einem Array von Wörterbüchern als Werten. Ich verstehe das. Was ist der Zweck des "?" zwischen [selectedFruit] und [selectedVariety]? – fbelfort

+0

Die neue Struktur ist ein Dictionary mit String als Schlüssel und einem Wert, der ein Dictionary mit einem String als Schlüssel und einem Array von Ints als Wert darstellt. Dictionary-Lookups geben immer ein optionales Ergebnis zurück, da der Schlüssel möglicherweise nicht existiert. Sie müssen das Ergebnis auspacken, um es zu verwenden. Das '?' Ist in diesem Fall als * optionales Verketten * bekannt und entpackt das erste Wörterbuch-Lookup, wenn es nicht 'nil' ist, so dass das zweite Wörterbuch-Lookup fortfahren kann. Wenn eines der Lookups "nil" zurückgibt, ist das Ergebnis der * optionalen Kette * "nil" und das 'if let' wird nicht auftreten. In jedem Fall ist dies völlig sicher. – vacawama

3

Erstens würde ich die Art ändern, wie das Wörterbuch leicht strukturiert ist. Anstatt ein Array von Arrays zu haben, ändern Sie es in ein Array von Wörterbüchern. So etwas wie folgt aus:

let fruits: [String:[String: [Int]]] = [ 
    "Apple": [ 
     "Gravenstein": [122,100], 
     "Ginger Gold": [119, 130], 
     "Jazz": [150, 190] 

    ], 

    "Grapes": [ 
     "Cabernet Sauvignon": [120,100], 
     "Merlot": [150, 130], 
     "Tempranillo": [130, 190] 

    ] 
] 

Sobald Sie getan haben, dass Sie einfach eine Methode wie folgt schreiben:

func getTotalValue(fruitName: String, varietyName: String) -> Int? { 

    guard let varieties = fruits[fruitName] else { return nil } 
    guard let values = varieties[varietyName] else { return nil } 

    return values.reduce(0, +) 
} 

Und es verwenden, etwa so:

getTotalValue(fruitName: "Apple", varietyName: "Gravenstein") 
0

Hier ist die Funktion, um deine Früchte zu finden. Ich habe auch Kommentare hinzugefügt, damit Sie den Container für eine einfachere Suche ändern können.

// it is enough to say your container is [String: Any] 
    let fruits: [String: Any] = [ 
     "Apple": [ 
      ["Gravenstein",122,100], 
      ["Ginger Gold", 119, 130], 
      ["Jazz", 150, 190] 

     ], 


    "Grapes": [ 
     ["Cabernet Sauvignon",120,100], 
     ["Merlot", 150, 130], 
     ["Tempranillo", 130, 190] 

    ] 
] 

func findFruits(name: String, type: String) -> (Int, Int)? { 
    // Declare nil tuple 
    var searchedFruitValues: (Int, Int)? 
    // First lets see if we have the fruit in the container 
    if let fruit = fruits[name] as? [[Any]]{ 
     // Iterate through every element 
     fruit.forEach({ (element) in 
      // If the first element is equal to the searched type, check the numbers 
      if type == (element.first as? String) { 
       // If they are integers, lets associate the value to searchedFruitValues 
       if let first = element[1] as? Int, let second = element[2] as? Int { 
        searchedFruitValues = (first, second) 
       } 
      } 
     }) 
    } 
    // Return nil or the found values 
    return searchedFruitValues 
} 

let searched = findFruits(name: "Apple", type: "Jazz") 
print(searched ?? "not found") 
0

Eine andere Lösung:

struct Fruit { 
    var name : String 
    var variety : [Variety] 
} 

struct Variety { 
    var name : String 
    var numbers : [Int] 

    func getNumbers() -> Int { 
     var result = 0 
     for value in self.numbers { 
      result += value 
     } 
     return result 
    } 
} 

//example data 
let apples = [ 
    Variety(name: "Gravenstein", numbers: [122, 100]), 
    Variety(name: "Ginger Gold", numbers: [119, 130]) 
] 

let grapes = [ 
    Variety(name: "Cabernet Sauvignon", numbers: [120,100]), 
    Variety(name: "Merlot", numbers: [150, 130]) 
] 


let fruits = [ 
    Fruit(name: "Apple", variety: apples), 
    Fruit(name: "Garpes", variety: grapes) 
] 

//the actual call for the Variety numbers 
    if let goldenGinger = fruits.first(where: { $0.name == "Apple"})?.variety.first(where: { $0.name == "Ginger Gold"}) { 
     print(goldenGinger.getNumbers()) 
    } 
Verwandte Themen