按指定索引对数组进行排序,在保持字母顺序的同时优先考虑布尔值

时间:2016-01-21 21:25:07

标签: ios arrays swift sorting

这个有点傻了!

基于this question,我根据另一个数组中的索引重新排序了一个对象数组:

// pop this in a playground:

struct DataObject {
    let id: String
    let name: String
    let isRequired: Bool

    init(_ id: String, _ name: String, _ isRequired: Bool) {
        self.id = id
        self.name = name
        self.isRequired = isRequired
    }
}

struct User {
    let sortingIndex: [String]

    init(_ sortingIndex: [String]) {
        self.sortingIndex = sortingIndex
    }
}


let a = [DataObject("1", "A", false), DataObject("2", "B", true), DataObject("3", "C", true), DataObject("4", "D", false)]

func sort(a: [DataObject], forUser user: User) -> [DataObject] {
    return a.sort { user.sortingIndex.indexOf($0.id) < user.sortingIndex.indexOf($1.id) }
}

let user = User(["1", "2", "4", "3"])

sort(a, forUser: user)

输出如下:

[{id "3", name "C", isRequired true}, {id "2", name "B", isRequired true}, {id "1", name "A", isRequired false}, {id "4", name "D", isRequired false}]

(大多数都很好!)

我想按字母顺序优先处理isRequired个数组的开头,所以我尝试了:

return a.sort { $0.isRequired ? $0.name < $1.name : user.sortingIndex.indexOf($0.id) < user.sortingIndex.indexOf($1.id) }
                                     \\ ^

(什么都不做)

或:

return a.sort { $0.isRequired ? $0.name > $1.name : user.sortingIndex.indexOf($0.id) < user.sortingIndex.indexOf($1.id) }
                                     \\ ^

(有效,但按字母顺序排列)

我希望它最终看起来像这样:

[
    {id "2", name "B", isRequired true}, 
    {id "3", name "C", isRequired true}, 
    {id "1", name "A", isRequired false}, 
    {id "4", name "D", isRequired false}
]

4 个答案:

答案 0 :(得分:1)

如果只需要$0$1中的一个,则无论名称如何,都应分别返回truefalse。所以这样的事情会起作用:

return a.sort {
        if $0.isRequired && $1.isRequired {
            return $0.name < $1.name
        }
        if $0.isRequired { return true }
        if $1.isRequired { return false }
        return user.sortingIndex.indexOf($0.id) < user.sortingIndex.indexOf($1.id)
    }

答案 1 :(得分:1)

将您的排序更改为:

a.sort { (lhs, rhs) -> Bool in
    if lhs.isRequired != rhs.isRequired { return lhs.isRequired }
    if lhs.name != hrs.name {return lhs.name < rhs.name}
    return user.sortingIndex.indexOf(lhs.id) < user.sortingIndex.indexOf(rhs.id)
}

首先检查isRequired,然后检查名称,最后检查用户索引。

答案 2 :(得分:1)

这是一种可爱的方式:

return a.sort({  $0.isRequired != $1.isRequired   ? $0.isRequired
               : $0.isRequired                    ? $0.name < $1.name
               : user.sortingIndex.indexOf($0.id) < user.sortingIndex.indexOf($1.id)
              })

你的是不同级别的排序,但是,更一般地说,多级排序条件总是具有相同的模式:

  $0.level1 != $1.level1     ? $0.level1 < $1.level1
: $0.level2 != $1.level2     ? $0.level2 < $1.level2
...
: $0.levelN-1 != $1.levelN-1 ? $0.levelN-1 < $1.levelN-1
: $0.levelN < $1.levelN

答案 3 :(得分:0)

您可以为>值定义Bool运算符,并使用它来对对象数组进行排序:

func >(lhs: Bool, rhs: Bool) -> Bool {
    return lhs && !rhs
}

let sortedObjects = sort(a, forUser: user).sort{$0.isRequired > $1.isRequired || $0.name < $1.name}