使用Swift在数组中查找重复元素

C0m*_*ade 23 arrays addressbook swift ios8

如何在数组中找到重复元素?我有一系列的电话号码所以在电话号码中我应该从右侧开始搜索到左侧并找到类似的6个整数.然后我应该打印出来.

Pat*_*ini 44

感觉〜聪明〜.鉴于一系列的Ints

let x = [1, 1, 2, 3, 4, 5, 5]
let duplicates = Array(Set(x.filter({ (i: Int) in x.filter({ $0 == i }).count > 1})))
// [1, 5]
Run Code Online (Sandbox Code Playgroud)

请注意,这对所有参与者来说都非常有效,包括编译器和你.

我只是炫耀.

编辑: lol有人对此表示赞同,这导致我重申,以防万一:请不要在生产或其他任何地方使用它.

  • 答案按预期工作.但它不是内存高效的解决方案.如果你在X-code Playground中运行Code,那么单行将运行57次.因此,如果您正专注于解决大型数据阵列.在这种情况下,我不会应用此解决方案. (4认同)

Rob*_*Rob 23

要查找重复项,您可以通过电话号码构建交叉引用,然后将其过滤为仅重复.例如,考虑:

let contacts = [
    Contact(name: "Rob",     phone: "555-1111"),
    Contact(name: "Richard", phone: "555-2222"),
    Contact(name: "Rachel",  phone: "555-1111"),
    Contact(name: "Loren",   phone: "555-2222"),
    Contact(name: "Mary",    phone: "555-3333"),
    Contact(name: "Susie",   phone: "555-2222")
]
Run Code Online (Sandbox Code Playgroud)

在Swift 4中,您可以使用以下命令构建交叉引用字典:

let crossReference = Dictionary(grouping: contacts, by: { $0.phone })
Run Code Online (Sandbox Code Playgroud)

要么

let crossReference = contacts.reduce(into: [String: [Contact]]()) {
    $0[$1.phone, default: []].append($1)
}
Run Code Online (Sandbox Code Playgroud)

然后,找到重复项:

let duplicates = crossReference
    .filter { $1.count > 1 }                 // filter down to only those with multiple contacts
    .sorted { $0.1.count > $1.1.count }      // if you want, sort in descending order by number of duplicates
Run Code Online (Sandbox Code Playgroud)

清楚地使用适合您的任何模型类型,但上面使用以下Contact类型:

struct Contact {
    let name: String
    let phone: String
}
Run Code Online (Sandbox Code Playgroud)

有许多方法可以实现这一点,所以我不会专注于上面的实现细节,而是专注于这个概念:通过某个键(例如电话号码)构建交叉引用原始数组,然后将结果过滤到只是那些具有重复值的键.


听起来你想要将这个反映重复的结构扁平化为单个联系人数组(我不知道你为什么要这样做,因为你失去了识别哪些是彼此重复的结构),但是如果你想这样做,你可以flatMap:

let flattenedDuplicates = crossReference
    .filter { $1.count > 1 }                 // filter down to only those with multiple contacts
    .flatMap { $0.1 }                        // flatten it down to just array of contacts that are duplicates of something else
Run Code Online (Sandbox Code Playgroud)

对于Swift 2或3的再现,请参阅此答案的先前版本.


Rob*_*way 20

斯威夫特 4+

2线,快速解决:

var numbers = [1,2,3,4,5,6,6,6,7,8,8]
let dups = Dictionary(grouping: numbers, by: {$0}).filter { $1.count > 1 }.keys

//Results: [6, 8]
Run Code Online (Sandbox Code Playgroud)


Ben*_*ohn 9

完全源自Rob 非常简洁的回答Array为了清楚起见,我已将其添加到扩展中并为中间步骤命名:

extension Array where Element: Hashable {
    func duplicates() -> Array {
        let groups = Dictionary(grouping: self, by: {$0})
        let duplicateGroups = groups.filter {$1.count > 1}
        let duplicates = Array(duplicateGroups.keys)
        return duplicates
    }
}

[1, 2, 2, 3, 1].duplicates() -> [1, 2]
Run Code Online (Sandbox Code Playgroud)


tik*_*hop 6

您可以使用"合并排序"来实现它,但是您需要进行一次修改,在合并步骤中您应该忽略重复项.

查找重复元素的最简单方法是,如果电话号码只是一个6位数字并且类型为Int,您可以对电话号码数组进行排序,然后对其进行过滤以查找重复项.

var phoneNumbers = [123456, 234567, 345678, 123456, 456789, 135790, 456789, 142638]

func findDuplicates(sortedArray array: [Int]) -> [Int]
{
    var duplicates: [Int] = []

    var prevItem: Int = 0
    var addedItem: Int = 0

    for item in array
    {
        if(prevItem == item && addedItem != item)
        {
            duplicates.append(item)
            addedItem = item
        }

        prevItem = item
    }

    return duplicates
}

func sortPhoneNumbers(phoneNumbers: [Int]) -> [Int]
{
    return phoneNumbers.sorted({ return $0<$1 })
}

sortPhoneNumbers(phoneNumbers)
findDuplicates(sortPhoneNumbers(phoneNumbers))
Run Code Online (Sandbox Code Playgroud)

此外,您可以通过不同方式实现findDuplicates方法:

使用Set(Swift 1.2+):

func findDuplicates(array: [Int]) -> [Int]
{
    var duplicates = Set<Int>()
    var prevItem = 0       

    for item in array
    {
        if(prevItem == item)
        {
            duplicates.insert(item)
        }

        prevItem = item
    }

    return Array(duplicates)
}
Run Code Online (Sandbox Code Playgroud)

等等.


Ant*_*ine 6

要根据属性筛选数组,可以使用此方法:

extension Array {

    func filterDuplicates(@noescape includeElement: (lhs:Element, rhs:Element) -> Bool) -> [Element]{
        var results = [Element]()

        forEach { (element) in
            let existingElements = results.filter {
                return includeElement(lhs: element, rhs: $0)
            }
            if existingElements.count == 0 {
                results.append(element)
            }
        }

        return results
    }
}
Run Code Online (Sandbox Code Playgroud)

根据Rob的联系人示例,您可以按照以下方式调用:

let filteredContacts = myContacts.filterDuplicates { $0.name == $1.name && $0.phone == $1.phone }
Run Code Online (Sandbox Code Playgroud)