Обновить значения в словаре на основе изменений, внесенных в другой словарь

Я хотел бы знать, есть ли способ автоматически обновлять значение в словаре на основе изменений, внесенных в значения в другом словаре. У меня есть 2 словаря следующим образом:

enum CharacterAttributes: String, Codable  {
    case strength
    case constitution
    case dexterity
    case intelligence
}

enum CharacterStats: String, Codable  {
    case maxHealthPoint
    case maxTacticPoint
    case maxActionPoint
    case movementSpeed
}

var attributes = [CharacterAttributes: Float]()
var stats = [CharacterStats: Float]()

Логика такова:

stats[.maxHealthPoint] = attributes[.constitution] *  100
stats[.maxTacticPoint] = (attributes[.dexterity] +  attributes[.intelligence]) * 1.5
stats[.maxActionPoint] = attributes[.constitution] * 10
stats[.movementSpeed] = attributes[.dexterity] + 70

Чего я хочу добиться, так это того, что всякий раз, когда значение изменяется из словаря атрибутов, соответствующие значения в статистике обновляются автоматически. Я знаю, что для обычной переменной я могу использовать ключевое слово DidSet, но как применить эту концепцию к словарям?

Заранее благодарю за любую помощь.

Значит, stats должно зависеть от attributes, а не наоборот, верно? Можно ли изменить stats напрямую? Можно ли делать stats[.maxHealthPoint] = 100 например?

Sweeper 25.07.2024 04:18

Да, статистика зависит от атрибутов, а не наоборот. однако определенное значение в статистике должно быть разрешено изменять напрямую. например stats[.movementSpeed] = 100

Bob 25.07.2024 04:31

Кажется, я что-то пропустил. Почему didSet не работает как решение? — И зачем именно эти словари? Разве структура не была бы проще?

matt 25.07.2024 04:33

Хорошо, если некоторую статистику можно установить, то когда эта статистика должна «синхронизироваться» с атрибутами? Когда stats[.movementSpeed] вернется к attributes[.dexterity] + 70 после того, как вы установили значение 100?

Sweeper 25.07.2024 04:35

Извините, правильный способ изменения скорости должен выглядеть так: stats[.movementSpeed] += someModifier. Таким образом, при изменении атрибутов[.dexterity] статистика[.movementSpeed] всегда должна оставаться синхронизированной. Кажется, Саш дал мне нужный ответ. Спасибо, в любом случае.

Bob 25.07.2024 05:33

Вы уверены, что словари — правильный способ хранения этой информации? Некоторые структуры с наблюдателями didSet сделают это очень легко.

Alexander 25.07.2024 05:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Попробуйте использовать наблюдатель DidSet после инкапсуляции словарей в класс:

import Foundation

enum CharacterAttributes: String, Codable {
    case strength
    case constitution
    case dexterity
    case intelligence
}

enum CharacterStats: String, Codable {
    case maxHealthPoint
    case maxTacticPoint
    case maxActionPoint
    case movementSpeed
}

class Character {
    private var _attributes = [CharacterAttributes: Float]() {
        didSet {
            updateStats()
        }
    }
    
    private var _stats = [CharacterStats: Float]()
    
    var attributes: [CharacterAttributes: Float] {
        get { _attributes }
        set {
            _attributes = newValue
            updateStats()
        }
    }
    
    var stats: [CharacterStats: Float] {
        get { _stats }
        set {
            _stats = newValue
        }
    }
    
    init(attributes: [CharacterAttributes: Float]) {
        self._attributes = attributes
        updateStats()
    }
    
    private func updateStats() {
        _stats[.maxHealthPoint] = (_attributes[.constitution] ?? 0) * 100
        _stats[.maxTacticPoint] = ((_attributes[.dexterity] ?? 0) + (_attributes[.intelligence] ?? 0)) * 1.5
        _stats[.maxActionPoint] = (_attributes[.constitution] ?? 0) * 10
        if _stats[.movementSpeed] == nil { // Allow manual setting
            _stats[.movementSpeed] = (_attributes[.dexterity] ?? 0) + 70
        }
    }
}

Пример использования:

var character = Character(attributes: [.constitution: 5, .dexterity: 3, .intelligence: 2])
print(character.stats)
character.attributes[.constitution] = 7
character.stats[.movementSpeed] = 100
character.attributes[.dexterity] = 4
print(character.stats)

Выход:

[SwiftPlayground.CharacterStats.maxHealthPoint: 500.0, SwiftPlayground.CharacterStats.maxTacticPoint: 7.5, SwiftPlayground.CharacterStats.maxActionPoint: 50.0, SwiftPlayground.CharacterStats.movementSpeed: 73.0]
[SwiftPlayground.CharacterStats.maxHealthPoint: 700.0, SwiftPlayground.CharacterStats.maxTacticPoint: 9.0, SwiftPlayground.CharacterStats.maxActionPoint: 70.0, SwiftPlayground.CharacterStats.movementSpeed: 100.0]

Это круто! Это именно то, что я искал. Спасибо.

Bob 25.07.2024 05:24

Другие вопросы по теме