2016-04-14 9 views
0

Допустим, у меня есть словари, как показано ниже, и вам нужен массив красных собак. Я решил, что мне нужно получить массив всех имен типа «собака» с использованием первого словаря, а затем использовать ключ имени и цвет для поиска в конечном словаре, чтобы получить [«Полли», «Джейк»] ве попытался с помощью петель, но не могу понять, как перебрать словарьСловарь Swift содержит

var pets = ["Polly" : "dog", "Joey" : "goldfish", "Alex" : "goldfish", "jake" : "dog"] 

var petcolor = ["Polly" : "red", "Joey" : "black", "Alex" : "yellow", "jake":red"] 
+1

Возможно, лучше использовать объекты, чем словари. – brimstone

ответ

1

правильное решение казалось бы чтобы создать структуру (или класс) Pet и собрать всю эту информацию в структуру и построить либо массив, либо словарь, полный этих значений.

struct Pet { 
    let name: String 
    let type: String 
    let color: String 

    init(name: String, type: String, color: String) { 
     self.name = name 
     self.type = type 
     self.color = color 
    } 
} 

Теперь давайте создадим массив из этих животных:

var goodPets = [Pet]() 

for (petName, petType) in pets { 
    guard let petColor = petcolor[petName] else { 
     // Found this pet's type, but couldn't find its color. Can't add it. 
     continue 
    } 

    goodPets.append(Pet(name: petName, type: petType, color: petColor)) 
} 

Теперь, когда мы заполнили goodPets, вытаскивая какое-либо конкретное подмножество домашних животных становится очень легко:

let redDogs = goodPets.filter { $0.type == "dog" && $0.color = "red" } 

И хотя этот ответ похож на множество заданий & по сравнению с другими ответами, главное преимущество вот как только мы построим массив goodPets, любой способ, которым мы хотим выкопать домашних животных, в конечном итоге становится более эффективным. И поскольку мы увеличиваем количество свойств, которые есть у домашних животных, это становится все более и более истинным по сравнению с другими ответами.


Если вы предпочитаете хранить свои объекты модели в словаре продолжает использовать имена в качестве ключей, мы можем сделать это так же хорошо, но фильтр выглядит немного незнакомца.

Построение словаря выглядит в основном тот же:

var goodPets = [String : Pet]() 

for (petName, petType) in pets { 
    guard let petColor = petcolor[petName] else { 
     // Found this pet's type, but couldn't find its color. Can't add it. 
     continue 
    } 

    goodPets[petName] = (Pet(name: petName, type: petType, color: petColor)) 
} 

Но фильтр немного отличается:

let redDogs = goodPets.filter { $0.1.type = "dog" && $0.1.color = "red" } 

Обратите внимание, что в обоих случаях redDogs имеет тип [Pet], то есть, массив значений Pet.

+0

Я собираюсь использовать это, поскольку планирую добавить критерии. Предположим, что пользователь вводит тип, а не цвет: есть ли способ игнорировать отсутствие критериев цвета и давать всем собакам без кучи if-заявлений? – user3015221

+0

@ user3015221 Твое лучшее из этого момента - это реализовать что-то *, которое работает *, а затем перейти к [Обзор кода] (http://codereview.stackexchange.com/help/on-topic), чтобы очистить его. – nhgrif

0

Вы можете перебирать словарь, как это:.

for key in pets.keys() { 
    if pets[key] == "Dog" { 

    } 
} 

Или:

for (name, pet) in pets { 
    if pet == "Dog" { 
    } 
} 
+0

Спасибо, работала безупречно! – user3015221

0

nhgrif, вероятно, правильно о структуре, но, чтобы ответить на этот буквальный вопрос:

let dogs = Set(pets.filter { $0.1 == "dog" }.map { $0.0 }) 
let redAnimals = Set(petscolor.filter { $0.1 == "red" }.map { $0.0 }) 

let redDogs = dogs.intersect(redAnimals) 

Каждый filter является блок, который работает на (ключ, значение) кортеж, тестирует значение и в конечном итоге создание словаря с только пары соответствия (ключ, значение). Каждый map затем преобразует этот фильтрованный словарь в массив, отбрасывая значения и просто сохраняя ключи.

Каждый массив преобразован в набор, поддерживающий операцию intersect. Затем intersect определяет пересечение двух результатов.

Смежные вопросы