【问题标题】:Sorting data in order按顺序对数据进行排序
【发布时间】:2017-02-20 18:25:34
【问题描述】:

我有一个从 Firebase 获取数据的函数。功能是:

private var levelsArr = [Level]()
func fetchLevels() {

    DataService.instance.levelsRef.observe(.value, with: { (snapshot) in
        print(snapshot)
        if let lvlsDict = snapshot.value as? Dictionary<String, AnyObject> {

            for(_, valueLvl) in lvlsDict {

                if let lvlDict = valueLvl as? Dictionary<String, AnyObject> {
                    if let lvlId = lvlDict["id"] as? Int, let lvlCoverImg = lvlDict["coverImage"] as? String, let lvlTitle = lvlDict["title"] as? String {
                      let level = Level(id: lvlId, coverImage: lvlCoverImg, title: lvlTitle)
                        self.levelsArr.append(level)
                        print(self.levelsArr)
                        DispatchQueue.main.async(execute: { 
                            self.collectionView?.reloadData()
                        })

                    }
                }
            }
        }

    })
    print(self.levelsArr)
}

当我运行应用程序时,控制台会给我这个:

[Repeat.Level(id: 0, coverImage: "lvl0", title: "Level0")]
[Repeat.Level(id: 0, coverImage: "lvl0", title: "Level0"), Repeat.Level(id: 2, coverImage: "lvl2", title: "Level2")]
[Repeat.Level(id: 0, coverImage: "lvl0", title: "Level0"), Repeat.Level(id: 2, coverImage: "lvl2", title: "Level2"), Repeat.Level(id: 3, coverImage: "lvl3", title: "Level3")]
[Repeat.Level(id: 0, coverImage: "lvl0", title: "Level0"), Repeat.Level(id: 2, coverImage: "lvl2", title: "Level2"), Repeat.Level(id: 3, coverImage: "lvl3", title: "Level3"), Repeat.Level(id: 1, coverImage: "lvl1", title: "Level1")]

当我打印快照时,它是有序的,但是当我获取数据并将每个级别放入一个数组时,它不再是有序的。

为什么要这样做,我怎样才能让我的数据像在快照中一样排序?

谢谢。


更新

进行以下更改:

    func fetchLevels() {
    DataService.instance.levelsRef.queryOrdered(byChild: "lvlId").observe(.value, with: { (snapshot) in
        print(snapshot)
        if let lvlsDict = snapshot.value as? Dictionary<String, AnyObject> {
            self.levelsArr.removeAll()
            for(_, valueLvl) in lvlsDict {

                if let lvlDict = valueLvl as? Dictionary<String, AnyObject> {
                    if let lvlId = lvlDict["id"] as? Int, let lvlCoverImg = lvlDict["coverImage"] as? String, let lvlTitle = lvlDict["title"] as? String {
                      let level = Level(id: lvlId, coverImage: lvlCoverImg, title: lvlTitle)
                        self.levelsArr.append(level)
                        DispatchQueue.main.async(execute: { 
                            self.collectionView?.reloadData()
                        })
                    }
                }
            }
        }

    })
}



override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        // Configure the cell

        let lvlCell = collectionView.dequeueReusableCell(withReuseIdentifier: lvlCellId, for: indexPath) as! lvlCell

        levelsReverseArr = levelsArr.reversed()

        print(levelsReverseArr)
        lvlCell.level = levelsReverseArr[indexPath.item]



        return lvlCell
    }

控制台结果:

Snap (levels) {
level0 =     {
    coverImage = lvl1;
    id = 0;
    title = Level1;
};
level1 =     {
    coverImage = lvl2;
    id = 1;
    title = Level2;
};
level2 =     {
    coverImage = lvl3;
    id = 2;
    title = Level3;
};

[Repeat.Level(id: 1, coverImage: "lvl1", title: "Level1"), Repeat.Level(id: 3, coverImage: "lvl3", title: "Level3"), Repeat.Level(id: 2, coverImage: "lvl2", title: "Level2"), Repeat.Level(id: 0, coverImage: "lvl0", title: "Level0")]

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    我不完全确定为什么 Firebase 喜欢“搞乱”数组,所以我无法回答您的问题,但要解决此问题,您可以使用 .queryOrdered(byChild:) 来订购快照,更改“id”任何可以订购您的物品的东西:

    DataService.instance.levelsRef.queryOrdered(byChild: "id").observe(.value, with: { (snapshot) in
    

    一旦数组已满或更新,您可能还需要反转数组...

    更新:

    如果你明白我的双关语,这希望应该“排序”你的问题,也就是说,如果 level id 是一个 int 并且你希望它被订购为 lvl 0...100?现在不需要.queryOrdered

    func insertionSort<T>(_ arr: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] {
        guard arr.count > 1 else { return arr }
    
        var b = arr
        for i in 1..<b.count {
            var y = i
            let temp = b[y]
            while y > 0 && isOrderedBefore(temp, b[y - 1]) {
                b[y] = b[y - 1]
                y -= 1
            }
            b[y] = temp
        }
        return b
    }
    

    你需要做的就是改变

    levelsReverseArr = levelsArr.reversed()
    

    sortedLevelArr = insertionSort(levelArr) { $0.id < $1.id }
    

    【讨论】:

    • 我根据您的更改结果编辑了问题。似乎不起作用还是我犯了一个错误?
    • 它似乎应该可以工作,我今天早上才使用该代码,尝试将 byChild 输入更改为数据库中的其他输入之一进行检查,我通常使用时间戳,并且可以在 10/10 工作
    • 那是没有意义的,我的头在燃烧
    • 我唯一能建议的是尝试一些假数据,比如数据库中的时间戳来测试对数组的任何更改?或打印“快照”以查看它是如何排序的,以查看查询是否正常
    • firebase.google.com/docs/database/rest/retrieve-data 这显示了不同的查询选项
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多