xcode 有没有办法只使用Swift 5+按名字和姓氏排序?

wz1wpwve  于 2022-12-14  发布在  Swift
关注(0)|答案(1)|浏览(100)

我一直在绞尽脑汁,试图找出一种方法来排序一个字符串的名字和姓氏。我有一个正常的排序实现(见下文),但想扩大它一点。
排序功能:

@objc func handleSortByName() {
        let sortedList: [List] = self.viewModel.names.sorted() { $0.fullName < $1.fullName }
        replaceNewList(newList: sortedList)

    }

我在考虑遍历字符串,检查空格后的字符是否小于下一个字符串的空格后的字符,但我完全搞不懂。

y1aodyip

y1aodyip1#

遍历字符串中的字符是可行的,但是考虑到名称由两个部分组成,需要分别进行比较,并且每个部分的长度都可能因名称而异,因此要正确处理和维护名称将是很棘手的。
一个更简单的方法是将名字拆分为分别包含名字和姓氏的内容,然后使用该内容进行比较。
给予个代码例子,我需要一些明确的格式,所以让我们假设你的名字看起来都像“Bobby Landry”,“Sarah McMillan”,等等...基本上第一个非空格子字符串是名字,后面是一个空格,后面是更多的非空格,形成姓氏,没有更多的空格。如果你的实际格式不同,你需要适当地修改FirstLast.init
我还假设主排序应该按姓排序,次排序按名排序。您可以修改func <实现来做您实际需要的事情。

@objc func handleSortByName() 
{
    struct FirstLast: Comparable
    {
        let first: Substring
        let last : Substring

        init(_ name: String)
        {
            guard let spaceIndex = name.firstIndex(of: " ") else {
                fatalError("Missing space - do something more appropriate here")
            }
            guard let lastNameStartIndex = name.index(after: spaceIndex) else {
                fatalError("No last name - do something more appropriate here")
            }
            self.first = name[..<spaceIndex]
            self.last  = name[lastNameStartIndex...]
        }

        // Primary sort by last name, secondary sort on first
        static func < (left: Self, right: Self) -> Bool
        {
            return left.last == right.last
                ? left.first < right.first
                : left.last < right.last
        }
    }

    let sortedList: [List] = self.viewModel.names.sorted() {
        FirstLast($0.fullName) < FirstLast($1.fullName)
    }
    replaceNewList(newList: sortedList)
}

我选择把FirstLast作为一个本地类型,只是因为我假设没有其他东西需要它。如果你认为它对其他代码有用,你可以把它移到handleSortByName之外。
如果没有太多的名字,这应该可以;然而,它会为每个比较构造一对FirstLast,因为它们只存在于比较闭包中,而且每个比较都需要搜索第一个空格来拆分名称。
对于大量的名字,在整个排序过程中只构造一次FirstLast示例会更有意义,这样它们就可以在所有的比较中重复使用。一种方法是将[List]Map到[FirstLast],然后对[FirstLast]数组的 indices 进行排序,然后用它来创建排序后的[List]

@objc func handleSortByName() 
{
    struct FirstLast: Comparable
    {
        // Same implementation as above
        ...
    }

    let firstLastNames = self.viewModel.names.map { FirstLast($0.fullName) }

    var firstLastIndices = [Int](firstLastNames.indices)
    firstLastIndices.sort { firstLastNames[$0] < firstLastNames[$1] }

    let sortedList: [List] = firstLastIndices.map { self.viewModel.names[$0] }

    replaceNewList(newList: sortedList)
}

相关问题