如何删除多个并行数组中的重复数据

时间:2017-10-18 19:01:51

标签: ios arrays swift

我正在尝试删除swift中具有多个相同值的相同精确顺序的某些数组元素 即

假设现在我有3个数组

array1 = [a,b,c,d,d,c,d]
array2 = [1,2,3,4,4,3,4]
array3 = [aa,bb,cc,dd,dd,cc,dd]

问题是:我需要从数组中删除共有3个重复值的元素

这意味着,我需要摆脱索引的元素:[4],[5],[6]来自数组1,2和3。

PS。 3个数组必须是分开的数组,并且不能重新排列它的顺序,因为它们有一些彼此相关的关键信息

任何建议都将不胜感激。

4 个答案:

答案 0 :(得分:3)

var array1 = ["a","b","c","d","d","c","d"]
var array2 = [1,2,3,4,4,3,4]
var array3 = ["aa","bb","cc","dd","dd","cc","dd"]
var set: Set<Int> = []   // you can use a set to check the duplicated elements

for index in array2.indices.reversed() { // reversed is necessary to remove your elements
    if !set.insert(array2[index]).inserted {
        array1.remove(at: index)
        array2.remove(at: index)
        array3.remove(at: index)
    }
}
array1  // ["a", "b", "c", "d"]
array2  // [1, 2, 3, 4]
array3  // ["aa", "bb", "cc", "dd"]

答案 1 :(得分:1)

元组是Equatable(假设它们的元素是Equatable)直到arity 6,我们可以利用这里将三个数组压缩成3元组序列,识别重复3 -tuple元素,并从原始的三个数组中删除与这些元组关联的索引。但是,元组不是Hashable,所以我们不会使用3元组,而是可以回退到存储三个值的实用程序Hashable类型(3元组确实匿名输入)。

实用程序类型:

struct ZippedElement: Hashable {
    let a: String
    let b: Int
    let c: String

    init(_ a: String, _ b: Int, _ c: String) {
        self.a = a
        self.b = b
        self.c = c
    }

    // Use a very simple common hashValue calculation, simply
    // falling back on the hashValue of the Int member.
    var hashValue: Int { return b.hashValue }

    static func ==(lhs: ZippedElement, rhs: ZippedElement) -> Bool {
        return lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.c
    }
}

这允许我们对array1array3执行过滤/变异操作,如下所示:

var seen = Set<ZippedElement>()
zip(zip(array1, array2), array3)
    .map { ZippedElement($0.0, $0.1, $1) }
    .enumerated().filter { !seen.insert($1).inserted }
    .map { $0.offset }.reversed()
    .forEach {
        array1.remove(at: $0)
        array2.remove(at: $0)
        array3.remove(at: $0)
    }

结果,在每个数组中删除了最后三个元素:

print(array1) // ["a", "b", "c", "d"]
print(array2) // [1, 2, 3, 4]
print(array3) // ["aa", "bb", "cc", "dd"]

您的示例数据设置不会对此处的不同解决方案构成许多挑战,但是,@ dasblinkenlight提出了一个很好的问题:

  

如果我用"dd"替换array3的{​​{1}},会改变所需的结果吗?

在这种情况下,我相信我们大多数人都认为应该保留所有原始数组中的第7个元素,因为&#34; vertical&#34;对于第7个元素(/列),所有三个数组上的zip组合都是唯一的。

对这样的修改示例应用与上述相同的方法:

"dx"

你的问题的另一个评论由@SteveKuo提出,说明我们大多数人的想法(对于所有问题都有一些有趣的算法练习),例如这个问题(索引跟踪单独的数组......) ):

  

似乎更合适的数据结构是创建array1 / 2/3属性的struct / class / tuple。

我相信这是你应该带着的核心答案,所以即使你明确说明了

  

... ps。 3个数组必须是分开的数组

您可能需要一个自定义类型的单个数组。

答案 2 :(得分:0)

您可以将数组放入一个集合(其本身不包含重复项),然后将其传回数组。

e.g。

var array2: [Int] = [1,2,3,4,4,3,4]
let set2 = Set<Int>(array2)
array2 = Array(set2).sorted()

如果您还需要针对其他数组设置逻辑,则可以执行set2.subtract(otherSequence)之类的操作。

答案 3 :(得分:0)

其他解决方案涵盖了一种工作方法,但所有这些都在O(n ^ 2)时间内完成,因为迭代遍历数组并重复调用remove(at:),这本身就是一个O(n)操作。

假设所有3个阵列在相同的位置都有重复,这里是一个功能性的O(n)方法,它使用交换,然后在结束时只修改一次数组。不确定性能有多重要,但这应该在更大的数据集上显着更快。

var array1 = ["a","b","c","d","d","c","d"]
var array2 = [1,2,3,4,4,3,4]
var array3 = ["aa","bb","cc","dd","dd","cc","dd"]

var set: Set<Int> = []

var lastIndex = 0
for index in array2.indices
{
    if set.insert(array2[index]).inserted
    {
        array1.swapAt(index, lastIndex)
        array2.swapAt(index, lastIndex)
        array3.swapAt(index, lastIndex)
        lastIndex += 1
    }
}

let numToRemove = array1.count - lastIndex
array1.removeLast(numToRemove)
array2.removeLast(numToRemove)
array3.removeLast(numToRemove)