如何根据一行中的值对Swift中的二维数组列进行排序?

时间:2019-05-24 12:03:06

标签: arrays swift sorting

如何根据其中一行的值对二维数组进行排序?

let array = [["X", "Y",   1,  2,  3,  4,  5],
             ["V", "W", "A","B","C","D","E"]
]

let sorted = [["X", "Y",   5,  4,  3,  2,  1],
              ["V", "W", "E","D","C","B","A"]
    ]

Swift Array.sort({e1, e2 in e1 < e2})传递行元素,而不传递列元素。

更糟糕的是,该行的前两列不得排序。

请记住,必须根据第1行的顺序重新排列第2行。因此,假设我们按第0行排序,而忽略第1 2列

[["X", "Y",   1,  2,  3,  4,  5],
 ["V", "W", "E","B","A","D","F"]]

应该成为

[["X", "Y",   5,  4,  3,  2,  1],
 ["V", "W", "F","D","A","B","E"]]

2 个答案:

答案 0 :(得分:0)

首先映射数组元素,然后从子数组中拆分前2个元素以跳过排序。现在,使用开关模式匹配对其余元素进行排序。然后将排序后的数组与前2个元素连接起来。

let array = [["X", "Y",   1,  2,  3,  4,  5],
             ["V", "W", "A","B","C","D","E"]]

let sorted = array.map { $0[..<2] + $0[2...].sorted(by: {
    switch ($0,$1) {
    case (let a as Int, let b as Int): return a > b
    case (let a as String, let b as String): return a > b
    case (let a as Date, let b as Date): return a > b
    case (_, _): return false
    }
})}.map { Array($0) }
print(sorted)
  

[[[“ X”,“ Y”,5,4,3,2,1],[“ V”,“ W”,“ E”,“ D”,“ C”,“ B”,“ A“]]

答案 1 :(得分:0)

这是我想出的解决方案-非常难看!!

extension Array where Element == Array<String> {
    /// Creates a totals row at the bottom
    /// ignore - number of columns to ignore at the start
    mutating func addTotalsRow(ignore: Int){
        // Create a totals row (top row)
        var totals = [String]()
        // Add columns if required
        if ignore > 0 {
            totals.append("Total")
            totals.append(contentsOf: repeatElement("", count: ignore - 1))

        }


        for row in self {
            for i in ignore..<row.count {

                let value = row[i].toDouble ?? 0.0
                if (i+1) > totals.count {
                    totals.append("0.0")
                }
                totals[i] = ((totals[i].toDouble ?? 0.0) + value).formatted4
            }
        }

        self.append(totals)

        return
    }

    /// Sort columnwise using values in 'row', ignoring first 'ignore' columns
    /// Also sorts the optional header row
    /// Returns (sortedRows, sortedHeaderRow)
    func columnSorted(_ sortRow: Int, ignoreColumnCount: Int, order: SortOrder = .ascending, headerRow: [String]?)->([[String]], [String]?) {

        // Now calculate a totals row
        var newHeader: [String]?

        // Create an array of objects holding the total and the column index
        var indexes = [IX]()

        let totals = self[sortRow]

        // Ignore the text columns
        for i in ignoreColumnCount..<totals.count {
            indexes.append(IX(total: totals[i], index: i))
        }
        // Sort IX by the totals
        indexes.sort(by: {ix1, ix2 in
            return order == .descending ? ix1.intTotal > ix2.intTotal : ix1.intTotal < ix2.intTotal})

        // Create the Totals data row
        var totalsRow = [String]()
        totalsRow.append(contentsOf: totals[0..<ignoreColumnCount])
        totalsRow.append(contentsOf: indexes.map({$0.total}))



        if let header = headerRow {
            newHeader = [String]()
            newHeader!.append(contentsOf: header[0..<ignoreColumnCount])
            for i in 0..<indexes.count {
                let ix = indexes[i].index
                if ((i+ignoreColumnCount)+1) > newHeader!.count {
                    newHeader!.append("")
                }
                newHeader![i+ignoreColumnCount] = header[ix]
            }
        }

        var newData = [[String]]()
        // newData.append(totalsRow)
        // Now do the same for all the rows in data
        for row in self {
            var newRow = [String]()
            newRow.append(contentsOf: row[0..<ignoreColumnCount])

            for i in 0..<indexes.count {
                let ix = indexes[i].index
                if ((i+ignoreColumnCount)+1) > newRow.count {
                    newRow.append("0.0")
                }
                newRow[i+ignoreColumnCount] = row[ix]
            }
            newData.append(newRow)
        }

        // Sort by count
        return (newData, newHeader)
    }
    /// Sort by column index 0...
    mutating func sort(by column: Int, order: SortOrder = .ascending) {

        guard column > 0 else {
            return
        }
        let index = column - 1

        self.sort(by: {r1, r2 in
            let count1 = (r1[index].toDouble ?? 0.0)
            let count2 = (r2[index].toDouble ?? 0.0)
            if let val = r1[index].toDouble {
                return order == .descending ? (r1[index].toDouble ?? 0.0) > (r2[index].toDouble ?? 0.0) : (r1[index].toDouble ?? 0.0) < (r2[index].toDouble ?? 0.0)
            } else {
                return order == .descending ? r1[index] > r2[index] : r1[index] > r2[index]
            }
        })
    }

    func sorted(by column: Int, order: SortOrder = .ascending, ignoreFirstRow: Bool = false)->[[String]] {

        guard column > 0 else {
            return self
        }
        let index = column - 1

        var resultSet = [[String]]()

        if ignoreFirstRow {
            // Save the first row
            let firstRow = self[0]

            let dataRows = self[1..<count].sorted(by: {r1, r2 in

                if let val = r1[index].toDouble {
                    return order == .descending ? (r1[index].toDouble ?? 0.0) > (r2[index].toDouble ?? 0.0) : (r1[index].toDouble ?? 0.0) < (r2[index].toDouble ?? 0.0)
                } else {
                    return order == .descending ? r1[index] > r2[index] : r1[index] < r2[index]
                }

            })
            resultSet.append(firstRow)
            resultSet.append(contentsOf: dataRows)
        } else {

            let dataRows = self[0..<count].sorted(by: {r1, r2 in

                if let val = r1[index].toDouble {
                    return order == .descending ? (r1[index].toDouble ?? 0.0) > (r2[index].toDouble ?? 0.0) : (r1[index].toDouble ?? 0.0) < (r2[index].toDouble ?? 0.0)
                } else {
                    return order == .descending ? r1[index] > r2[index] : r1[index] < r2[index]
                }

            })
            resultSet.append(contentsOf: dataRows)
        }

        return resultSet
    }
    func printArray(){
        for row in self {
            print("\(row)")
        }
    }
}