Swift - 对数组的子集进行排序

时间:2022-06-15 16:00:10

I currently have a tableview with a lot of users, but I would like to sort the users in a specific order, not just ascending or descending. Let's say I have an array with the following users.

我目前有一个包含大量用户的tableview,但我想按特定顺序对用户进行排序,而不仅仅是升序或降序。假设我有一个包含以下用户的数组。

"User1", "1st grade"
"User2", "1st grade"
"User3", "kids"
"User4", "6th grade"
"User5", "5th grade"
"User6", "2nd grade"
"User7", "kids"
"User8", "juniors"

How can I order my array so that all the students who are in kids class are the first to be displayed, followed by all the classes with numbers (in order) and then all the Juniors.

如何订购我的数组,以便所有在小学班级的学生都是第一个被展示的学生,然后是所有带有数字的班级(按顺序),然​​后是所有的三年级学生。

I want an array that can display this

我想要一个可以显示这个的数组

"User3", "kids"
"User7", "kids"
"User1", "1st grade"
"User2", "1st grade"
"User6", "2nd grade"
"User5", "5th grade"
"User4", "6th grade"
"User8", "juniors"

Edit: Updated the text to make clear that the array has two columns, not just one string.

编辑:更新了文本以清除数组有两列,而不只是一个字符串。

Was able to achieve it by using the line below

能够通过使用下面的行来实现它

let sortedArray = 
self.userArray.sorted(by: { $0.SchoolGrade!.gradeLongName().contains("Kids") || 
$1.SchoolGrade!.gradeLongName().contains("Juniors") })

3 个解决方案

#1


2  

Swift has a sort algorithm that lets you sort using a closure. The closure should return true if the first arguement comes before the second argument.

Swift有一个排序算法,允许您使用闭包进行排序。如果第一个论点出现在第二个论点之前,则闭包应该返回true。

let sortedArray = user.sorted(by: {

    ($0.gradeLongName().contains("kids") 
     || $1.gradeLongName()contains("juniors")  
     || $0.gradeLongName() < $1.gradeLongName())
    && !($0.gradeLongName().contains("kids") && $1.gradeLongName().contains("kids"))
    && !($0.gradeLongName().contains("juniors") && $1.gradeLongName().contains("juniors"))
})

Should do the trick. The closure says two elements are in the right order if the first one has kids in it, the second one has juniors in it or they are alphabetically in the right order. The last two subexpressions make the closure return false when two elements both have kids or both have juniors which is a requirement for the API

应该做的伎俩。关闭说如果第一个元素中有两个元素,第二个元素中有小孩,或者它们按正确的顺序按字母顺序排列,则两个元素的顺序正确。最后两个子表达式使得闭包返回false,当两个元素都有孩子或两者都有后代时,这是API的要求

You can also use trailing closure syntax here:

您还可以在此处使用尾随闭包语法:

let sortedArray = user.sorted{ ($0.gradeLongName().contains("kids") 
     || $1.gradeLongName()contains("juniors")  
     || $0.gradeLongName() < $1.gradeLongName())
    && !($0.gradeLongName().contains("kids") && $1.gradeLongName().contains("kids")
    && !(($0.gradeLongName().contains("juniors") && $1.gradeLongName().contains("juniors")) }

Also you can do an in place sort on a mutable array with sort(by:)

你也可以使用sort(by :)对可变数组进行排序。

API docs are here: https://developer.apple.com/documentation/swift/array/2296815-sorted

API文档在这里:https://developer.apple.com/documentation/swift/array/2296815-sorted

#2


0  

You should create three separate arrays, use filter to get the appropriate results, then sort them individually. After that, you should join the three arrays by a simple additional operation.

您应该创建三个单独的数组,使用过滤器来获取适当的结果,然后单独对它们进行排序。之后,您应该通过一个简单的附加操作加入三个数组。

#3


0  

What you are trying to sort is not common sort routine. So firstly, check your data structure for better sort solution.

你想要排序的不是常见的排序例程。首先,检查您的数据结构以获得更好的排序解决方案。

But if you insist use your string list to sort, then you can try the following code (very ugly) which can be run on the playground:

但是如果你坚持使用你的字符串列表进行排序,那么你可以尝试下面的代码(非常难看),它可以在操场上运行:

import UIKit

var array = [String]()
array.append("User1, 1st grade")
array.append("User2, 1st grade")
array.append("User3, kids")
array.append("User4, 6th grade")
array.append("User5, 5th grade")
array.append("User6, 2nd grade")
array.append("User7, kids")
array.append("User8, Juniors")

let kidsArray = array.filter { $0.lowercased().contains("kids") }.sorted()
let gradeArray = array.filter { $0.lowercased().contains("grade") }.sorted { $0.components(separatedBy: ",").last! < $1.components(separatedBy: ",").last! }
let juniorArray = array.filter { $0.lowercased().contains("juniors") }.sorted()

var finalArray = [String]()
finalArray.append(contentsOf: kidsArray)
finalArray.append(contentsOf: gradeArray)
finalArray.append(contentsOf: juniorArray)

print(finalArray)

Print:

["User3, kids", "User7, kids", "User1, 1st grade", "User2, 1st grade", "User6, 2nd grade", "User5, 5th grade", "User4, 6th grade", "User8, Juniors"]

[“User3,kids”,“User7,kids”,“User1,1st grade”,“User2,1st grade”,“User6,2nd grade”,“User5,5th grade”,“User4,6th grade”,“User8” ,小辈“]

#1


2  

Swift has a sort algorithm that lets you sort using a closure. The closure should return true if the first arguement comes before the second argument.

Swift有一个排序算法,允许您使用闭包进行排序。如果第一个论点出现在第二个论点之前,则闭包应该返回true。

let sortedArray = user.sorted(by: {

    ($0.gradeLongName().contains("kids") 
     || $1.gradeLongName()contains("juniors")  
     || $0.gradeLongName() < $1.gradeLongName())
    && !($0.gradeLongName().contains("kids") && $1.gradeLongName().contains("kids"))
    && !($0.gradeLongName().contains("juniors") && $1.gradeLongName().contains("juniors"))
})

Should do the trick. The closure says two elements are in the right order if the first one has kids in it, the second one has juniors in it or they are alphabetically in the right order. The last two subexpressions make the closure return false when two elements both have kids or both have juniors which is a requirement for the API

应该做的伎俩。关闭说如果第一个元素中有两个元素,第二个元素中有小孩,或者它们按正确的顺序按字母顺序排列,则两个元素的顺序正确。最后两个子表达式使得闭包返回false,当两个元素都有孩子或两者都有后代时,这是API的要求

You can also use trailing closure syntax here:

您还可以在此处使用尾随闭包语法:

let sortedArray = user.sorted{ ($0.gradeLongName().contains("kids") 
     || $1.gradeLongName()contains("juniors")  
     || $0.gradeLongName() < $1.gradeLongName())
    && !($0.gradeLongName().contains("kids") && $1.gradeLongName().contains("kids")
    && !(($0.gradeLongName().contains("juniors") && $1.gradeLongName().contains("juniors")) }

Also you can do an in place sort on a mutable array with sort(by:)

你也可以使用sort(by :)对可变数组进行排序。

API docs are here: https://developer.apple.com/documentation/swift/array/2296815-sorted

API文档在这里:https://developer.apple.com/documentation/swift/array/2296815-sorted

#2


0  

You should create three separate arrays, use filter to get the appropriate results, then sort them individually. After that, you should join the three arrays by a simple additional operation.

您应该创建三个单独的数组,使用过滤器来获取适当的结果,然后单独对它们进行排序。之后,您应该通过一个简单的附加操作加入三个数组。

#3


0  

What you are trying to sort is not common sort routine. So firstly, check your data structure for better sort solution.

你想要排序的不是常见的排序例程。首先,检查您的数据结构以获得更好的排序解决方案。

But if you insist use your string list to sort, then you can try the following code (very ugly) which can be run on the playground:

但是如果你坚持使用你的字符串列表进行排序,那么你可以尝试下面的代码(非常难看),它可以在操场上运行:

import UIKit

var array = [String]()
array.append("User1, 1st grade")
array.append("User2, 1st grade")
array.append("User3, kids")
array.append("User4, 6th grade")
array.append("User5, 5th grade")
array.append("User6, 2nd grade")
array.append("User7, kids")
array.append("User8, Juniors")

let kidsArray = array.filter { $0.lowercased().contains("kids") }.sorted()
let gradeArray = array.filter { $0.lowercased().contains("grade") }.sorted { $0.components(separatedBy: ",").last! < $1.components(separatedBy: ",").last! }
let juniorArray = array.filter { $0.lowercased().contains("juniors") }.sorted()

var finalArray = [String]()
finalArray.append(contentsOf: kidsArray)
finalArray.append(contentsOf: gradeArray)
finalArray.append(contentsOf: juniorArray)

print(finalArray)

Print:

["User3, kids", "User7, kids", "User1, 1st grade", "User2, 1st grade", "User6, 2nd grade", "User5, 5th grade", "User4, 6th grade", "User8, Juniors"]

[“User3,kids”,“User7,kids”,“User1,1st grade”,“User2,1st grade”,“User6,2nd grade”,“User5,5th grade”,“User4,6th grade”,“User8” ,小辈“]