3
\$\begingroup\$

I recently answered a question that had me wondering if I could simplify this below code without creating an extra function:

for object in objects {
    if let type = object["type"] where !type.isEmpty, let name = object["name"] {

        print(pokemonTypeDefenseChart[type])
        for weakness in pokemonTypeDefenseChart[type]! {
            if pokemonWeaknessChart[weakness] == nil {
                pokemonWeaknessChart[weakness] = []
            }
            pokemonWeaknessChart[weakness]?.append(name)
        }
    }

    if let typeTwo = object["typeTwo"] where !typeTwo.isEmpty, let name = object["name"] {
        for weakness in pokemonTypeDefenseChart[typeTwo]! {
            if pokemonWeaknessChart[weakness] == nil {
                pokemonWeaknessChart[weakness] = []
            }
            pokemonWeaknessChart[weakness]?.append(name)
        }
    }
}

Essentially the code loops through objects (list of pokemon) and is designed to add all of the pokemon weak to type (and optionally typeTwo).

I ended up just refactoring the for statements inside the if let statements into a function, but I was wondering if it was possible to compress these without an extra function. The only difference is the type.

I know I could simplify it a bit by using a map instead of for loops but I wanted to keep it more understandable for the question.

Any ideas?

\$\endgroup\$
0
2
\$\begingroup\$

You could do something like:

for x in ["type", "typeTwo"] {
    if let type = object[x] where !type.isEmpty,
        let name = object["name"],
        defenseChart = pokemonTypeDefenseChart[type] { /* ... */ }
}

Also, to simplify the rest of your code, you could extend Dictionary like this:

extension Dictionary {
    subscript(key: Key, fallback fallback: Value) -> Value {
        get { return self[key] ?? fallback }
        set { self[key] = newValue }
    }
}

This allows you to replace this:

for weakness in defenseChart {
    if pokemonWeaknessChart[weakness] == nil {
        pokemonWeaknessChart[weakness] = []
    }
    pokemonWeaknessChart[weakness]?.append(name)
}

by this:

for weakness in defenseChart {
    pokemonWeaknessChart[weakness, fallback: []].append(name)
}
\$\endgroup\$
3
  • \$\begingroup\$ Is there a reason that you provide a set for the Dictionary.subscript(_:fallback:)? It seems like that that interface is not contributing anything. \$\endgroup\$ – CAD97 Aug 12 '16 at 19:35
  • \$\begingroup\$ @CAD97 By providing both a getter and a setter, we can apply mutating functions to that subscript (in this case append). \$\endgroup\$ – Tim Vermeulen Aug 12 '16 at 19:47
  • \$\begingroup\$ @TimVermeulen ah, that makes sense. \$\endgroup\$ – CAD97 Aug 12 '16 at 19:48
0
\$\begingroup\$

I can't test this right now, but something like this might work, I am assuming each type in pokemonTypeDefenseChart is an array, so I combine the arrays , then loop through it once. Normally I would filter out dups, but you can't add functions, so I check if the name does not exist, and append if it doesn't

for object in objects {
    if let name = object["name"] {
        let defense = (
            (object["type"].flatMap({pokemonTypeDefenseChart[$0]}) ?? []) + 
            (object["typeTwo"].flatMap {pokemonTypeDefenseChart[$0]} ?? []))

        for weakness in defense {
            if pokemonWeaknessChart[weakness] == nil {
                pokemonWeaknessChart[weakness] = []
            }
            if (pokemonWeaknessChart[weakness]?.contains(name)) == nil {
                pokemonWeaknessChart[weakness]?.append(name)
            }
            print(pokemonWeaknessChart[weakness] )
        }
    }

}

Thanks to @TimVermeulen for cleaning up some parts of the answer

\$\endgroup\$
15
  • \$\begingroup\$ I am assuming that if I call defense chart on isEmpty, that I am getting a nil result \$\endgroup\$ – Knight0fDragon Aug 12 '16 at 19:29
  • \$\begingroup\$ type ?? "" doesn't make sense, because type is non-optional at that point. Same applies to typeTwo. \$\endgroup\$ – Tim Vermeulen Aug 12 '16 at 19:49
  • \$\begingroup\$ @TimVermeulen why wouldnt it be optional, we do not know if object["type"] exists \$\endgroup\$ – Knight0fDragon Aug 12 '16 at 19:52
  • \$\begingroup\$ @TimVermeulen I added a space to help distinguish the brace (This is why I like the brace on the next line lol) \$\endgroup\$ – Knight0fDragon Aug 12 '16 at 19:54
  • \$\begingroup\$ Oh! The double space between if and let might have added to the confusion, because it aligns the let statements. Either way, why not add type and typeTwo to the if let? \$\endgroup\$ – Tim Vermeulen Aug 12 '16 at 19:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.