Ios 从firebase数据库检索计算平均值
我正在创建一个iOS应用程序,它为每个地方使用地名和评级。我已经把这件事做好了。我的意思是,我将数据保存到我的数据库中,我也可以读取它们。唯一的问题是,当我阅读它们时,我希望通过计算每个位置的平均值将它们加载到我的tableviewcell上。看截图,如果你不明白,请让我编辑答案 表格视图Ios 从firebase数据库检索计算平均值,ios,swift,uitableview,firebase,firebase-realtime-database,Ios,Swift,Uitableview,Firebase,Firebase Realtime Database,我正在创建一个iOS应用程序,它为每个地方使用地名和评级。我已经把这件事做好了。我的意思是,我将数据保存到我的数据库中,我也可以读取它们。唯一的问题是,当我阅读它们时,我希望通过计算每个位置的平均值将它们加载到我的tableviewcell上。看截图,如果你不明白,请让我编辑答案 表格视图 import UIKit import FirebaseDatabase class PlacesTableViewController: UITableViewController { //MA
import UIKit
import FirebaseDatabase
class PlacesTableViewController: UITableViewController {
//MARK: Properties
@IBOutlet weak var placesTableView: UITableView!
var dbRef:FIRDatabaseReference?
var places = [Places]()
private var loadedLabels = [String: String]()
private var loadedRatings = [String: Int]()
override func viewDidLoad()
{
super.viewDidLoad()
dbRef = FIRDatabase.database().reference()
// Loads data to cell.
loadData()
}
override func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
//return the number of rows
return places.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
// Table view cells are reused and should be dequeued using a cell identifier.
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? PlacesTableViewCell else {
fatalError("The dequeued cell is not an instance of PlacesTableView Cell.")
}
let place = places[indexPath.row]
cell.placeLabel.text = place.name
cell.ratingControl.rating = place.rating
return cell
}
private func loadData()
{
dbRef!.observe(.childAdded, with: {
(placeSnapshot) in
//print("Adding place \(placeSnapshot.key)...")
let labels = placeSnapshot.childSnapshot(forPath: "placeLabel")
for (key, label) in labels.value as! [String: String] {
self.updatePlace(key, label: label)
}
let ratings = placeSnapshot.childSnapshot(forPath: "rating")
for (key, rating) in ratings.value as! [String: Int] {
self.updatePlace(key, rating: rating)
}
})
}
private func updatePlace(_ key: String, label: String? = nil, rating: Int? = nil)
{
if let label = label {
loadedLabels[key] = label
}
if let rating = rating {
loadedRatings[key] = rating
}
guard let label = loadedLabels[key], let rating = loadedRatings[key] else {
return
}
if let place = Places(name: label, rating: rating) {
places.append(place)
placesTableView.reloadData()
}
}
}
Firebase
将数据加载到tableview的我的代码
import UIKit
import FirebaseDatabase
class PlacesTableViewController: UITableViewController {
//MARK: Properties
@IBOutlet weak var placesTableView: UITableView!
var dbRef:FIRDatabaseReference?
var places = [Places]()
private var loadedLabels = [String: String]()
private var loadedRatings = [String: Int]()
override func viewDidLoad()
{
super.viewDidLoad()
dbRef = FIRDatabase.database().reference()
// Loads data to cell.
loadData()
}
override func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
//return the number of rows
return places.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
// Table view cells are reused and should be dequeued using a cell identifier.
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? PlacesTableViewCell else {
fatalError("The dequeued cell is not an instance of PlacesTableView Cell.")
}
let place = places[indexPath.row]
cell.placeLabel.text = place.name
cell.ratingControl.rating = place.rating
return cell
}
private func loadData()
{
dbRef!.observe(.childAdded, with: {
(placeSnapshot) in
//print("Adding place \(placeSnapshot.key)...")
let labels = placeSnapshot.childSnapshot(forPath: "placeLabel")
for (key, label) in labels.value as! [String: String] {
self.updatePlace(key, label: label)
}
let ratings = placeSnapshot.childSnapshot(forPath: "rating")
for (key, rating) in ratings.value as! [String: Int] {
self.updatePlace(key, rating: rating)
}
})
}
private func updatePlace(_ key: String, label: String? = nil, rating: Int? = nil)
{
if let label = label {
loadedLabels[key] = label
}
if let rating = rating {
loadedRatings[key] = rating
}
guard let label = loadedLabels[key], let rating = loadedRatings[key] else {
return
}
if let place = Places(name: label, rating: rating) {
places.append(place)
placesTableView.reloadData()
}
}
}
放置swift
import UIKit
class Places {
//MARK: Properties
var name: String
var rating: Int
//MARK:Types
struct PropertyKey {
static let name = "name"
static let rating = "rating"
}
//MARK: Initialization
init?(name: String, rating: Int) {
// Initialize stored properties.
self.name = name
self.rating = rating
// Initialization should fail if there is no name or if the rating is negative.
// The name must not be empty
guard !name.isEmpty else {
return nil
}
// The rating must be between 0 and 5 inclusively
guard (rating >= 0) && (rating <= 5) else {
return nil
}
}
}
导入UIKit
学额{
//马克:财产
变量名称:String
风险值评级:整数
//标记:类型
结构属性键{
静态let name=“name”
静态let rating=“额定值”
}
//标记:初始化
初始化?(名称:字符串,等级:Int){
//初始化存储的属性。
self.name=名称
自我评价=评价
//如果没有名称或评级为负值,初始化应失败。
//名称不能为空
卫兵!名字。我还有空吗{
归零
}
//评级必须介于0和5之间(包括0和5)
guard(rating>=0)&(rating这是一个非常详细的答案,但它将迭代rating节点的子节点并计算平均值
let parentRef = self.dbRef.child("Paradosiako - Panorama")
let ratingRef = parentRef.child("rating") // rating node
ratingRef.observe(.value, with: { snapshot in
let count = snapshot.childrenCount
var total: Double = 0.0
for child in snapshot.children {
let snap = child as! FIRDataSnapshot
let val = snap.value as! Double
total += val
}
let average = total/Double(count)
print(average)
})
编辑
要遍历所有位置并获得平均值,代码如下
let placesRef = self.dbRef.child("akapnapp")
placesRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let placeSnap = child as! FIRDataSnapshot
let ratingsSnap = placeSnap.childSnapshot(forPath: "rating")
let count = ratingsSnap.childrenCount
var total: Double = 0.0
for child in ratingsSnap.children {
print(child)
let snap = child as! FIRDataSnapshot
let val = snap.value as! Double
total += val
}
let average = total/Double(count)
print(average)
}
})
显示代码的输出正确。我的子节点被命名为a、b、c,而不是问题中的childByAutoId,但它以任何方式工作
Snap (a) 3
Snap (b) 3
3.0
Snap (a) 2
Snap (b) 4
Snap (c) 5
3.67
据我所知,您希望在应用程序中使用四舍五入的双精度整数,而不是双精度整数。只要更改loadData()
函数中的代码,它就会对您起作用。此外,您还将调用updatePlace()
。请批准Jay的答案,他编写了代码
private func loadData()
{
dbRef!.observe(.childAdded, with: {
(placeSnapshot) in
let parentRef = self.dbRef?.child(placeSnapshot.key)
let ratingRef = parentRef?.child("rating")
ratingRef?.observe(.value, with: { snapshot in
let count = snapshot.childrenCount
var total: Double = 0.0
for child in snapshot.children {
let snap = child as! FIRDataSnapshot
let val = snap.value as! Double
total += val
}
let average = total/Double(count)
print("Average for \(placeSnapshot.key) = \(Int(round(average)))")
self.updatePlace("" , label: placeSnapshot.key, rating: Int(round(average)))
})
})
}
不清楚您在问什么。您是否正在尝试获取某个地点的平均评分?如果是,则需要读取每个地点的评分节点,并平均子节点的值;(2+4+5)/3?是否有错误消息?是否有一些代码没有按预期的方式工作?与其向我们展示所有代码,不如选择一个妨碍您的特定内容并加以描述。例如,可能有不了解fire base的人可以提供帮助。缩小问题范围。@Jay是的,这就是我想要的。@Mozahler我在那里另一个函数中的错误不是读取值。当用户添加新位置时,tableview尝试更新并崩溃,但如果他重新打开应用程序,则会显示“新位置”在tableview上正确显示。这是我问题中的一个问题。那么是您的代码崩溃的问题,还是您需要知道如何读取节点并找到数字序列的平均值的问题?谢谢您的回答,但编译器说PlacesTableViewController没有成员“ref”
self。ref是对您的firebase数据库,即ref=FIRDatabase.database().reference()。在您的情况下,它似乎被称为dbRef。更新了答案以反映这一点。@Jay她需要对数据库中的每个位置都这样做。@Alexandredis谢谢。我知道这一点,但认为OP可以从我的代码片段中推断出来。更新了答案以确保完整性。@RoulaChiouma我更新了答案并为您编写了代码。它将在主数据库节点中的所有位置并计算平均值。为什么在第一个节点中有第二个观察值?添加的.childAdded将返回节点中的所有内容,因此评分将已经在快照中。这将返回每个位置的平均评分。例如,Markiz的平均值=3 Paradosiako的平均值-Panorama=3Not w我的意思是。结果节点包含在placeSnapshot中,因此没有理由再次访问数据库以获取相同的数据。@Jay Okay:明白了!