2

I need to search each object in my array "heroes" for each hero(abathur, chromie, etc...) who has an item in it's synergy array equal to "Xul".("Xul" will eventually get changed to a variable input by the user). Then I need to increase the "pickValue" property for each of those that match.

So in this example the search would match chromie and increase its pick value.

this filter below lets me put the matched items into another array but i don't think filter will work for what i want because i need to keep the array "heroes" in tact and just increase the property "pickValue"

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

I've driven myself crazy looking for how to do this and I can't find it. The tutorial i've been following doesn't touch on this either. Below is the other relevant info.

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)
2
  • The end result of what I'm trying to do would be the array "heroes" with abathur who has a pickValue of 0 and chromie who has a pickValue of 1. Everything else, should be the same. Commented Jul 21, 2016 at 20:27
  • filter does not modify the original collection, it simply creates a new array with the matched items. Commented Jul 21, 2016 at 22:07

4 Answers 4

1

All the answers provided are right and they will allow you to modify the pickValue in you original array without losing any element.

The reason for that is that heroes:[Hero] is an array of objects not an array of Structs. When you manipulate an array of objects with .map(), .filter() and the likes, the new array you obtain contains references to the same object instances as you original array. So making changes from the new arrays actually modifies the Hero in you original array as well.

If Hero had been a Struct instead then you would indeed have had the problem you seem to be worried about.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you so much for clarifying this. I was unaware that the new array was simply a reference. That means that everyone here is right and I appreciate your answers. Sorry for being a noob.
I have a follow up question. In another part of my program I want to be able to duplicate the Array “heroes” and all of the variables and be able to edit those pick values separately from the original. So I would be able to have a chromie.pickValue = 1 and a chromie.pickValue = 0 I would imagine that to accomplish this I would have to create a new class and inherit from Hero. Then I would have to initialize all of the Heroes like chromie with another name, so like chromieA. Is this the correct / best way to do what I want?
Ideally you should post a new question for this. But you don't really need a new class. You can implement a duplicate() function in Hero which would create a new instance of Hero and copy the current object's attributes into it before returning the new instance. Then heroes.map{$0.duplicate()} will give you a new array with independent copies of your heroes and chromies.
0

You'll probably want to use a map() or flatMap() function for this. If you do a Google search for "Swift high order functions" and look for those two you will see a few really good articles on how to use them for what you're looking for.

2 Comments

I don't think either of these will work because they change the underlying array "heroes" and I want to keep it in tact. Map(), as i understand it transforms the array and changes its composition.
map (and filter and other similar methods) return new collections containing the specified objects. The original collection (heroes in this case) is left intact.
0

This works for me with your class:

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

}

In actual practice you can test it with:

print(chromie.pickValue)

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

print(chromie.pickValue)

Edit: Clarification of issue

2 Comments

Thank you for your quick response but this doesn't do what I'm looking for. I don't want to transform or lose any elements of the array heroes, and I don't want to make a new array of matched Items. I just want to edit the pick value property of any object hero, whose property "synergy" matches a given value.
@Apple I updated my answer to reflect for you, but it's very similar.
0

Just to clarify, filter does not modify the collection it is called on. It creates a new collection for you. So your original idea should work fine. If you want to test this, try calling filter on an array defined as a constant (using let).

However, here is another way to do what you are asking:

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

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

Printing the results like this:

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

Gives:

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

Appending to synergyList and re-running the forEach will update the pickValue's accordingly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.