2016-07-21 4 views
2

Мне нужно искать каждый объект в массиве «героев» для каждого героя (abathur, chromie и т. Д.), У которого есть элемент в синергетическом массиве, равном «Xul», . («Xul» в конечном итоге будет изменен на переменный ввод пользователем). Затем мне нужно увеличить свойство pickValue для каждого из них.Поиск массива внутри массива объекта

Таким образом, в этом примере поиск будет соответствовать хромированию и увеличить его значение выбора.

Этот фильтр ниже позволяет мне помещать согласованные элементы в другой массив, но я не думаю, что фильтр будет работать для того, что я хочу, потому что мне нужно сохранить массив «героев» в такт и просто увеличить свойство «pickValue»

let filteredHeroes = heroes.filter({ $0.synergy.contains("Xul") }) 

Я с ума сошел, ища, как это сделать, и я не могу его найти. Учебник, за которым я следил, также не затрагивает этого. Ниже приведена другая соответствующая информация.

class Hero{ 

    var name: String 
    var role: String 
    var synergy: [String] 
    var strong: [String] 
    var weak: [String] 
    var pickValue = 0 

    init(name: String, role: String, synergy: [String], strong: [String], weak: [String]){ 
     self.name = name 
     self.role = role 
     self.synergy = synergy 
     self.strong = strong 
     self.weak = weak 
    } 

} 
// there are about 50 of these "heroes" 
    var abathur = Hero(name: "Abathur", role: "Ranged Specialist", synergy: ["Illidan", "Chromie"], strong: ["Tracer", "Murky"], weak: ["Zeratul", "Nova"]) 
    var chromie = Hero(name: "Chromie", role: "Ranged Assassin", synergy: ["Xul", "Johanna"], strong: ["Abathur", "Zagara"], weak: ["Tracer", "Greymane"]) 


var heroes = [Hero]() 
heroes.append(abathur) // appended all heroes 
heroes.append(chromie) 
+0

Конечным результатом того, что я пытаюсь сделать, будет массив «героев» с абатуром, у которого есть pickValue 0 и chromie, у кого есть pickValue 1. Все остальное должно быть одинаковым. – Apple

+0

'filter' не изменяет исходную коллекцию, он просто создает новый массив с соответствующими элементами. –

ответ

1

Все предоставленные ответы являются правильными, и они позволят вам изменить pickValue в исходном массиве без потери какого-либо элемента.

Причина в том, что герои: [Герой] - это массив объектов, а не массив структур. Когда вы манипулируете массивом объектов с помощью .map(), .filter() и подобных, новый массив, который вы получаете, содержит ссылки на те же экземпляры объектов, что и исходный массив. Поэтому внесение изменений из новых массивов фактически изменяет героя в вашем исходном массиве.

Если бы Герой был Структурой, тогда у вас действительно была бы проблема, о которой вы, кажется, беспокоитесь.

+0

Большое вам спасибо за разъяснение этого. Я не знал, что новый массив был просто ссылкой. Это означает, что все здесь правы, и я ценю ваши ответы. Извините за нобе. – Apple

+0

У меня есть следующий вопрос. В другой части моей программы я хочу иметь возможность дублировать «героев» массива и все переменные и иметь возможность редактировать эти значения выбора отдельно от оригинала. Так что я мог бы иметь chromie.pickValue = 1 и chromie.pickValue = 0 Я бы предположил, что для этого мне нужно было бы создать новый класс и наследовать от Hero. Тогда мне придется инициализировать всех героев, таких как chromie, с другим именем, так же, как chromieA. Это правильный/лучший способ делать то, что я хочу? – Apple

+0

В идеале вы должны задать новый вопрос. Но вам не нужен новый класс. Вы можете реализовать функцию duplicate() в Hero, которая создаст новый экземпляр Hero и скопирует в него атрибуты текущего объекта перед возвратом нового экземпляра. Тогда heroes.map {$ 0.duplicate()} предоставит вам новый массив с независимыми копиями ваших героев и хромистов. –

0

Вы, вероятно, хотите использовать map() или flatMap() функцию для этого. Если вы выполните поиск Google для функций Swift высокого порядка и посмотрите на эти два, вы увидите несколько действительно хороших статей о том, как их использовать для того, что вы ищете.

+0

Я не думаю, что любой из них будет работать, потому что они меняют основной массив «героев», и я хочу сохранить его в такте. Map(), поскольку я понимаю, что он преобразует массив и изменяет его состав. – Apple

+0

'map' (и' filter' и другие подобные методы) возвращают * новые * коллекции, содержащие указанные объекты. Оригинальная коллекция ('heroes' в этом случае) остается нетронутой. –

0

Это работает для меня с классом:

func updatePickValue(heroes: [Hero], withValue: Int, forSynergy: String) { 
    let filteredResults = heroes.filter({$0.synergy.contains(forSynergy)}) 
    for hero in filteredResults { 
     hero.pickValue = withValue 
    } 

} 

В реальной практике вы можете проверить его:

print(chromie.pickValue) 

updatePickValue(heroes, withValue: 1, forSynergy: "Xul") 

print(chromie.pickValue) 

Edit: Разъяснение вопроса

+0

Благодарим вас за быстрый ответ, но это не делает то, что я ищу. Я не хочу преобразовывать или терять какие-либо элементы героев массива, и я не хочу создавать новый массив совпадающих элементов. Я просто хочу отредактировать свойство выбора значения любого героя объекта, чье свойство «синергия» соответствует заданному значению. – Apple

+0

@Apple Я обновил свой ответ, чтобы задуматься, но он очень похож. –

0

Просто для уточнения, filter делает не изменять коллекцию, на которую она вызывается. Он создает для вас новую коллекцию. Поэтому ваша оригинальная идея должна работать нормально. Если вы хотите проверить это, попробуйте позвонить filter в массив, определенный как константа (с использованием let).

Однако, вот еще один способ сделать то, что вы спрашиваете:

var synergyList:Set<String> = ["Xul"] 

heroes.forEach { (hero:Hero) ->() in 
    hero.pickValue = synergyList.intersect(hero.synergy).count 
} 

Печать результатов, как это:

for hero in heroes { 
    print("Hero: \(hero.name), Pick Value: \(hero.pickValue)") 
} 

дает:

Hero: Abathur, Pick Value: 0 
Hero: Chromie, Pick Value: 1 

прилагая к synergyList и перезапуск forEach обновит pickValue соответственно.

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