在Swift中,我说有两个阵列:
var array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
var array2: [Int] = [1, 0, 2, 0, 3]
现在,我想按升序对array1进行排序,并相应地重新索引array2,以便我得到
array1 = [1.2, 1.5, 2.4, 10.9, 20.4]
array2 = [1, 3, 0, 0, 2]
使用Swift函数或语法有一种简单的方法吗?
我知道我可以构建一个功能来跟踪索引,但我很好奇是否有更优雅的解决方案。
答案 0 :(得分:34)
let array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
let array2: [Int] = [1, 0, 2, 0, 3]
// use zip to combine the two arrays and sort that based on the first
let combined = zip(array1, array2).sorted {$0.0 < $1.0}
print(combined) // "[(1.2, 1), (1.5, 3), (2.4, 0), (10.9, 0), (20.0, 2)]"
// use map to extract the individual arrays
let sorted1 = combined.map {$0.0}
let sorted2 = combined.map {$0.1}
print(sorted1) // "[1.2, 1.5, 2.4, 10.9, 20.0]"
print(sorted2) // "[1, 3, 0, 0, 2]"
一起排序超过2个阵列
如果要排序3个或更多阵列,可以sort
其中一个阵列及其offset
,使用map
提取offsets
,然后使用map
命令其他数组:
let english = ["three", "five", "four", "one", "two"]
let ints = [3, 5, 4, 1, 2]
let doubles = [3.0, 5.0, 4.0, 1.0, 2.0]
let roman = ["III", "V", "IV", "I", "II"]
// Sort english array in alphabetical order along with its offsets
// and then extract the offsets using map
let offsets = english.enumerated().sorted { $0.element < $1.element }.map { $0.offset }
// Use map on the array of ordered offsets to order the other arrays
let sorted_english = offsets.map { english[$0] }
let sorted_ints = offsets.map { ints[$0] }
let sorted_doubles = offsets.map { doubles[$0] }
let sorted_roman = offsets.map { roman[$0] }
print(sorted_english)
print(sorted_ints)
print(sorted_doubles)
print(sorted_roman)
输出:
["five", "four", "one", "three", "two"] [5, 4, 1, 3, 2] [5.0, 4.0, 1.0, 3.0, 2.0] ["V", "IV", "I", "III", "II"]
答案 1 :(得分:7)
你可以&#34;链接&#34;每个数组的项目通过映射索引来创建元组数组,然后在提取原始数组之前根据第一个数组的值对元组进行排序。
assert(array1.count == array2.count, "The following technique will only work if the arrays are the same length.")
let count = array1.count
// Create the array of tuples and sort according to the
// first tuple value (i.e. the first array)
let sortedTuples = (0..<count).map { (array1[$0], array2[$0]) }.sort { $0.0 < $1.0 }
// Map over the sorted tuples array to separate out the
// original (now sorted) arrays.
let sortedArray1 = sortedTuples.map { $0.0 }
let sortedArray2 = sortedTuples.map { $0.1 }
答案 2 :(得分:3)
此部分由 @vacawama 对Swift 4语法的答案翻译
let array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
let array2: [Int] = [1, 0, 2, 0, 3]
// use zip to combine the two arrays and sort that based on the first
let combined = zip(array1, array2).sorted(by: {$0.0 < $1.0})
print(combined) // "[(1.2, 1), (1.5, 3), (2.4, 0), (10.9, 0), (20.0, 2)]"
// use map to extract the individual arrays
let sorted1 = combined.map {$0.0}
let sorted2 = combined.map {$0.1}
print(sorted1) // "[1.2, 1.5, 2.4, 10.9, 20.0]"
print(sorted2) // "[1, 3, 0, 0, 2]"
上述逻辑可以扩展为三个或更多阵列:
<强>(慢)强>
let array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
let array2: [Int] = [1, 0, 2, 0, 3]
let array3: [Float] = [3.3, 1.1, 2.5, 5.1, 9.0]
// use zip to combine each (first, n.th) array pair and sort that based on the first
let combined12 = zip(array1, array2).sorted(by: {$0.0 < $1.0})
let combined13 = zip(array1, array3).sorted(by: {$0.0 < $1.0})
// use map to extract the individual arrays
let sorted1 = combined12.map {$0.0}
let sorted2 = combined12.map {$0.1}
let sorted3 = combined13.map {$0.1}
正如 @Duncan C 指出的那样,这种方法效率不高,因为第一个数组是重复排序的。应该使用 @ vacawama的方法,在Swift 4语法中是:
<强>(快)强>
let offsets = array1.enumerated()sorted(by: {$0.element < $1.element}).map {$0.offset}
let sorted1 = offsets.map {array1[$0]}
let sorted2 = offsets.map {array2[$0]}
let sorted3 = offsets.map {array3[$0]}
答案 3 :(得分:0)
尽管不是特别优雅,但是在处理必须比较的对象数组时,其顺序未知且甚至可能不共享相同长度的简单解决方案是循环“有序“数组,在无序数组中找到匹配的对象,并将其附加到新的空数组中:
var sorted: [Foo] = []
// Loop the collection whose order will define the other
for item in originalOrder {
// Find the item in the unsorted collection
if let next = unsortedItems.first(where: { $0 === item }) {
// Move the item to the new collection, thus achieving order parity
sorted.append(next)
}
}
当您有一个提供转换后版本的集合的操作很有用时,该集合可能具有0..<original.count
个项目的任意顺序,并且您想使用指针/对象相等性返回到原始顺序。
如果您需要额外维护索引奇偶校验,则可以跳过if let
并将first(where:)
的结果直接附加到sorted
中,这会将nil
放入空白。
请注意,此示例解决方案将另外充当重复项或不重复项(可能不是您想要的)的筛选器。修改以适应您的需求。