Есть ли способ вызвать данные с помощью функции дженериков?

У меня есть простая структура и модель данных:

struct Phone: Identifiable {
    var id = UUID()
    var size: String
    var model: String
    var price: Int
}

let PhoneData = [
    Phone(size: "L", model: "New", price: 500),
    Phone(size: "X", model: "Old", price: 400),
    Phone(size: "X", model: "New", price: 600),
    Phone(size: "M", model: "New", price: 650)
]

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

я пробовал это

func returnWhatever<T>(whichProperty: T) -> Any {
    let phone = PhoneData[0]
    return phone.T
}

Но он печатает «Значение типа« Телефон »не имеет члена« Т »».

Я не хочу иметь три функции для каждого свойства модели данных, как эта для размера:

func returnWhatever() -> String {
    let phone = PhoneData[0]
    return phone.size
}

Не могли бы вы мне помочь, пожалуйста?

size и model оба являются Strings.
Jessy 11.12.2020 11:49

Очень незначительное замечание, но я бы посоветовал начинать PhoneData с заглавной буквы. Я бы предложил phoneData или, поскольку это не Data, возможно, phoneArray или просто phones.

Rob 11.12.2020 14:03

Вам нужна функция, которая возвращает значения только для первого элемента массива, какая польза от такой функции? И почему бы не использовать такие свойства, как phoneData.first?.size, phoneData.first?.model и phoneData.first?.price

Joakim Danielson 11.12.2020 14:34

@ Роб, да, ты прав, я делал это в спешке, моя ошибка

schwartz grossman 11.12.2020 17:20

@Joakim, это часть более крупного проекта, это упрощенный пример, я просто ищу лучшее решение, вместо того, чтобы использовать 3 функции, я хочу использовать 1

schwartz grossman 11.12.2020 17:20

И с моим предложением вы не будете использовать никакую функцию, а только свойства. Я просто не вижу, что функция, которую вы хотите, добавляет какую-либо ценность, но, возможно, я что-то упускаю

Joakim Danielson 11.12.2020 17:27

да, ваше предложение полностью справедливо. однако в нашем проекте мы используем еще один параметр и несколько условий, просто ищем здесь принцип. но спасибо!!

schwartz grossman 11.12.2020 18:07
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
93
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Phone.propertyOfSomePhone(\.price)
extension Phone {
  static let all: [Self] = [
    .init(size: "L", model: "New", price: 500),
    .init(size: "X", model: "Old", price: 400),
    .init(size: "X", model: "New", price: 600),
    .init(size: "M", model: "New", price: 650)
  ]

  static func propertyOfSomePhone<Property>(_ property: (Self) -> Property) -> Property {
    property(all[0])
  }
}

позвольте мне немного перефразировать: я хочу, чтобы функция возвращала значение (String или Int) на основе ввода (whatProperty), которое является свойством телефона (Size, Model, Price): поэтому я называю это returnWhatever ( whichProperty: size) и возвращает «L» или returnWhatever(whatProperty: price) и возвращает 500. И значения взяты из телефона в позиции 0 в массиве.

schwartz grossman 11.12.2020 12:30

Это не то, что говорит ваш вопрос, но это то, что в моем ответе.

Jessy 11.12.2020 12:49

да, вы правы, моя ошибка, извините, спасибо за вашу помощь!

schwartz grossman 11.12.2020 17:04
Ответ принят как подходящий

Вы можете использовать выражение key-path:

struct Phone: Identifiable {
    var id = UUID()
    var size: String
    var model: String
    var price: Int
}

let phones = [
    Phone(size: "L", model: "New", price: 500),
    Phone(size: "X", model: "Old", price: 400),
    Phone(size: "X", model: "New", price: 600),
    Phone(size: "M", model: "New", price: 650)
]

func returnWhatever<T>(_ property: KeyPath<Phone, T>) -> T {
    let phone = phones[0]
    return phone[keyPath: property]
}

А потом

let value = returnWhatever(\.price)

Или, как сказал Джесси , вы можете использовать замыкание, потому что Swift 5.2 позволяет использовать ключевые пути в качестве функций ( см. SE-0249). Таким образом:

func returnWhatever<T>(_ block: (Phone) -> T) -> T {
    let phone = phones[0]
    return block(phone)
}

И снова этот синтаксис выражения ключ-путь работает:

let value = returnWhatever(\.price)

большой! спасибо за подробное описание, выражение key-path для меня новая тема

schwartz grossman 11.12.2020 17:11

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