簡體   English   中英

在 Swift 中,如何根據另一個數組對一個數組進行排序?

[英]In Swift how can I sort one array based on another array?

在 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 函數或語法的簡單方法?

我知道我可以構建一個函數來完成它並可以跟蹤索引,但我很好奇是否有更優雅的解決方案。

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]"

將兩個以上的數組排序在一起

如果您有 3 個或更多數組要一起排序,則可以sort其中一個數組及其offset進行sort ,使用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"]

您可以通過映射索引來“鏈接”每個數組的項目以創建一個元組數組,然后在提取原始數組之前根據第一個數組的值對元組進行排序。

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 }

斯威夫特 4

這部分翻譯自@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]}

雖然沒有特別的優雅,與對象數組必須進行比較,並且其命令沒有已知的,並且可能甚至不共享相同的長度工作時,一個簡單的解決辦法是循環中的“有序”陣列,發現在無序匹配對象數組,並將其附加到一個新的空數組中:

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放入空格中。

請注意,此示例解決方案還將作為過濾器,用於過濾重復或不在原始文件中的項目,這些項目可能是您想要的,也可能不是。 根據您的需要進行修改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM