如何根据其中一行的值对二维数组进行排序?
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"]]
答案 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)")
}
}
}