簡體   English   中英

排序字符串數組,有異常 Swift

[英]Sort string array with exceptions Swift

我想按字母順序對字符串數組進行排序,但除了某些元素應始終在數組中排序第一和第二。 以下是數組的元素:

["cat", "dog", "bird", "zebra", "elephant"]

我希望它按字母順序排序,但zebra總是第一, cat總是第二,所以排序后它應該看起來像:

["zebra", "cat", "bird", "dog", "elephant"]

這就是我的處理方式:

    let animals = ["cat", "dog", "bird", "zebra", "elephant"]
    
    animals = animals.sorted(by: { first, second in
        if first == "zebra" {return true}
        if first == "cat" {return true}
        return first < second
    })

它首先返回斑馬,但不是貓第二

當元素按升序排列時,傳遞給sorted(by:)的閉包應該返回true ,否則返回false 除非您同時檢查第一個值和第二個值,否則您無法判斷元素是否按升序排列。 這就是為什么當第一個值為“zebra”或“cat”時返回true是行不通的——並不是所有的基礎都被覆蓋了。

一種解決方案是使用switch語句根據您正在查看的值指定比較邏輯:

let animals = ["cat", "dog", "bird", "zebra", "elephant"].sorted {
    switch ($0, $1) {
    case ("zebra", "cat"): // zebra is before cat
        return true
    case ("cat", "zebra"): // cat is not before zebra
        return false
    case ("cat", _), ("zebra", _): // zebra/cat are before everything
        return true
    case (_, "cat"), (_, "zebra"): // zebra/cat are not after anything
        return false
    case let (lhs, rhs): // alphabetical order
        return lhs < rhs
    }
}
// ["zebra", "cat", "bird", "dog", "elephant"]

如果這看起來有點過度設計,那是因為它是。 像這樣覆蓋你的所有基礎是很困難的,所以我絕對建議你看看你的用例,並考慮你是否真的需要這樣做。 如果你能擺脫一些更簡單的事情,那可能是你最好的選擇。 例如:

let animals = ["zebra", "cat"] + ["dog", "bird", "elephant"].sorted()
// ["zebra", "cat", "bird", "dog", "elephant"]

或者,如果animals數組無法修改,另一種選擇是硬編碼異常:

let exceptions = ["zebra", "cat"]
let otherAnimals = animals.filter { !exceptions.contains($0) }.sorted()
let sortedResult = exceptions + otherAnimals
// ["zebra", "cat", "bird", "dog", "elephant"]

你要的答案是:

var animals = ["cat", "dog", "bird", "zebra", "elephant"]

animals = animals.sorted(by: { first, second in
    if first == "cat" && second == "zebra" {return false;}
    if second == "cat" && first == "zebra" {return true;}                          
    if first == "zebra" || first == "cat" {return true;}
    if second == "zebra" || second == "cat" {return false;}
    
    return first < second
})

您甚至可以在排序之前嘗試調用animals.shuffle()以檢查排序是否有效,而不管輸入順序如何。

這是一種更易讀的方法,盡管效率可能較低:

var animals = ["cat", "dog", "bird", "zebra", "elephant"]

animals = animals.sorted();

var wordIndex:Int = animals.firstIndex(where: {$0 == "zebra"})!;
animals.insert(animals.remove(at: wordIndex), at: 0);

wordIndex = animals.firstIndex(where: {$0 == "cat"})!;
animals.insert(animals.remove(at: wordIndex), at: 1);

或者,如果您想要更通用的版本:

 func sortAndPrepend(inputArr: [String], prependWords: [String]) -> [String]{
    var array = inputArr.sorted();
    
    var wordIndex:Int;
    for i in 0...prependWords.count-1 {
        wordIndex = array.firstIndex(where: {$0 == prependWords[i]}) ?? -1;
        if (wordIndex != -1) {
            array.insert(array.remove(at: wordIndex), at: i);
        }
    }
    return array;
}

您可以使用枚舉首先按案例聲明順序進行比較的事實,然后按字典順序按有效負載值進行比較。 此功能在 Swift 5.3 中實現,請參閱

如果我們用“zebra”和“cat”案例定義一個枚舉類型,首先排序

enum AnimalOrder: Comparable {
    case zebra
    case cat
    case other(String)
    
    init(animal: String) {
        switch animal {
        case "zebra": self = .zebra
        case "cat": self = .cat
        default: self = .other(animal)
        }
    }
}

然后只需使用即可實現所需的排序

let animals = ["cat", "dog", "bird", "zebra", "elephant"]
let sorted = animals.sorted(by: {
    AnimalOrder(animal: $0) < AnimalOrder(animal: $1)
})

print(sorted) // ["zebra", "cat", "bird", "dog", "elephant"]

這種方法可以很容易地擴展到涵蓋更多“特殊情況”。

暫無
暫無

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

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