【问题标题】:Swift struct array distinct on one column (best approach)Swift 结构数组在一列上不同(最佳方法)
【发布时间】:2022-06-10 23:39:45
【问题描述】:

在这个例子中,我通过循环遍历每个值并附加到一个 tmp 数组来使我的结构数组与众不同。我想知道是否有更有效的方法来做到这一点。

struct DistinctListOnName{
    init(){
        let alist: [myList] = [myList(id: 1, name: "Jeff", status: "A"),
                             myList(id: 2, name: "Mike", status: "A"),
                             myList(id: 3, name: "Mike", status: "B"),
                             myList(id: 4, name: "Ron", status: "B")]
        
        var tmp: [myList] = []
        for i in alist{
            if (tmp.filter({ item in
                item.name == i.name
            }).count == 0) {
                tmp.append(i)
            }
        }
        print(tmp)
    }
}

struct myList {
    var id: Int
    var name: String
    var status: String
    init(id: Int, name: String, status: String){
        self.id = id
        self.name = name
        self.status = status
    }
}

上面的代码产生了这个预期的输出

[(id: 1, name: "Jeff", status: "A"), (id: 2, name: "Mike", status: "A"), (id: 4, name: "Ron", status: "B")]

感谢您的帮助!!

【问题讨论】:

  • 为什么要保留myList(id: 2, name: "Mike", status: "A") 而不是myList(id: 2, name: "Mike", status: "B")?因为它在列表中?
  • @Larme 是的,它只会根据列表的顺序删除重复项。
  • 一种方法是Dictionary(zip(alist.map(\.name), alist), uniquingKeysWith: { (first, _) in first }).values
  • 另一个是alist.reduce(into: [:]) { if $0[$1.name] == nil { $0[$1.name] = $1 }}.values

标签: swift


【解决方案1】:

你的描述让我想起了 Leetcode 中的第 26 题。

这道题最有效的方法是遍历数组,检测出重复的元素将其存放在数组的右边部分,遍历完后全部删除。因为一次移除数组中的一个元素,移除后的元素需要一个一个移到自身的前面

我把它作为一个泛型函数作为 Array 的扩展(要求元素实现 Equatable 协议):

extension Array where Element: Equatable {
    /// Description: remove duplicates without breaking order
    mutating func removeDuplicates() {
        guard self.count > 1 else {
            return
        }
        
        let numsCount = self.count
        var slow = 1
        
        for i in 1 ..< numsCount {
            if self[i - 1] != self[i] {
                self[slow] = self[i]
                slow += 1
            }
        }
        
        self.removeSubrange(slow ..< numsCount)
    }
}

所以你的结构应该修改为:

struct myList: Equatable {
    var id: Int
    var name: String
    var status: String
    init(id: Int, name: String, status: String){
        self.id = id
        self.name = name
        self.status = status
    }
    
    static func == (_ lhs: myList, _ rhs: myList) -> Bool {
        return lhs.name == rhs.name
    }
}

用法:

var alist: [myList] = [myList(id: 1, name: "Jeff", status: "A"),
                     myList(id: 2, name: "Mike", status: "A"),
                     myList(id: 3, name: "Mike", status: "B"),
                     myList(id: 4, name: "Ron", status: "B")]

alist.removeDuplicates()

print(alist)
//[(id: 1, name: "Jeff", status: "A"), (id: 2, name: "Mike", status: "A"), (id: 4, name: "Ron", status: "B")]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多