Лучшие практики для объединения массивов @published в режиме реального времени?

Поэтому я пишу код, который может находить ближайших пользователей как локально (MultiPeers и Bluetooth Low Energy), так и через сеть (используя базу данных в реальном времени для поиска ближайших пользователей по их местоположению).

    class ViewModel: ObservableObject{

    @Published nearbyMultipeers: [User]  = []
    @Published nearbyBluetoothUsers: [User]  = []
    @Published nearbyGeoUsers: [User]  = []


    // This gets the nearby users by GeoLocation and updates the nearbyGeoUsers array 
    func getNearbyUsersByGeoLocation(){ /* ... */ } 
   
   // This will loop through all of the nearby users obtained via multipeer and grab their user data from the database and append it to the nearbyMultipeers array 
    func getUsersFromPeers(nearbyPeers: [Peer])( /* ... */ )

    

  
   


}

Теперь эти списки будут постоянно обновляться (поскольку мультипиры работают только тогда, когда приложение находится на переднем плане, и, естественно, вы будете входить и выходить из зоны действия ближайших пользователей).

Проблема в том, что время от времени будут дублироваться данные, nearbyBluetoothUsers может содержать некоторые nearbyMultipeers, nearbyGeoUsers могут содержать некоторые nearbyBluetoothUsers и т. д. Мне нужен способ отобразить список всех этих пользователей в режиме реального времени без отображения повторяющихся данных.

Для простоты предположим, что я показываю их в виде списка

struct NearbyUsersView: View {

       // This observable object contains information on the nearby peers //(multipeers)
       // This is how I get the nearby peers 
       @ObservableObject var multipeerDataSource: MultipeerDataSource

       var body: some View {

           VStack{

              // Ideally I would display them in a scrollable list of some sort, this is 
                  // just to illustrate my issue 

                  ForEach(viewModel.$allUsersExcludingDuplicates){. user in 
                            
                           Text(user.name) 
     
                    }

         }
           .onAppear{
 
                      viewModel.getNearbyUsersByGeoLocation()
                      

}
           .onChange(of: multipeerDataSource.$nearbyPeers) { nearbyPeers

            // this array contains the nearby peers (users) 
           // We have to actually convert it to a `User`, or fetch the user data because //the objects here won't be the actual data it may just contain the user Id or some sort // so we have to grab the actual data 
            viewModel.getUsersFromPeers(nearbyPeers)

} 



    }

}

Я пропустил захват через bluetooth, так как это не нужно для понимания проблемы.

Теперь единственное, что я могу придумать в NearbyUsersView, это сделать

ForEach((viewModel.nearByMultipeers + viewModel.nearbyBluetoothUsers + viewModel.nearbyGeoUsers).removeDuplicates()) { user in  /* ... */ }

Но что-то мне подсказывает, что я не получу ожидаемых результатов

Трудно не видеть User, но если предположить, что это Equatable, вы можете просто использовать Set, чтобы убедиться, что вы не возвращаете дубликаты при объединении массивов.

jnpdx 17.03.2022 20:00
Стоит ли изучать 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
1
27
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы можете просто использовать вычисляемую переменную в своем ViewModel, предполагая, что User соответствует Equatable следующим образом:

public var nearbyUsers: Set<User> {
   Set(nearbyMultipeers).union(Set(nearbyBluetoothUsers).union(Set(nearbyGeoUsers)))
}

Это преобразует ваши массивы в наборы и создает один набор несколькими объединениями. Наборы не могут иметь дубликатов. Если вам это нужно как массив, вы можете сделать это:

public var nearbyUsers: [User] {
   Array(Set(nearbyMultipeers).union(Set(nearbyBluetoothUsers).union(Set(nearbyGeoUsers))))
}

Наконец, если User соответствует Comparable, вы можете вернуть отсортированный массив следующим образом:

public var nearbyUsers: [User] {
   Array(Set(nearbyMultipeers).union(Set(nearbyBluetoothUsers).union(Set(nearbyGeoUsers)))).sorted()
}

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