如果两个项目相同,如何比较Swift中的两个数组并对其中一个数组进行变异

如果两个项目相同,如何比较Swift中的两个数组并对其中一个数组进行变异,swift,Swift,我想比较两个数组,这意味着它们的每一项 如果此数组中的两项相同,我需要运行一些代码。 到目前为止,我已经用两个For循环实现了这一点,但是评论中有人说这不太好,因为我也遇到了一个错误 有人知道我可以用哪种代码达到这个目的吗 顺便说一句:这是我以前使用的代码: var指数=0 对于阵列1中的项目1{ 对于Array2中的第2项{ 如果Item1==Item2{ //在这里,我想把一些代码,如果项目是相同的 } } //在本例中,索引是一个计数器,它计算我在数组1中的哪个位置。 指数+=1 } 好的

我想比较两个数组,这意味着它们的每一项

如果此数组中的两项相同,我需要运行一些代码。 到目前为止,我已经用两个For循环实现了这一点,但是评论中有人说这不太好,因为我也遇到了一个错误

有人知道我可以用哪种代码达到这个目的吗

顺便说一句:这是我以前使用的代码:

var指数=0 对于阵列1中的项目1{ 对于Array2中的第2项{ 如果Item1==Item2{ //在这里,我想把一些代码,如果项目是相同的 } } //在本例中,索引是一个计数器,它计算我在数组1中的哪个位置。 指数+=1 } 好的,我会再次描述我的意思: 我想比较两个数组。如果有一些项目相同,我想从数组A/Array 1中删除该项目。
好的,如果这样做有效的话,我想再添加一些语句,只有当该项的参数具有特殊值时,我才可以删除该项,但我认为我可以单独执行此步骤。

如果要比较来自不同数组的项,需要为该项添加可平衡协议

例如:

您需要决定通过哪些属性来比较项目。在我的情况下,我比较的名字

如果你想支持这个

好的,我会再次描述我的意思:我想比较两个 数组。如果有一些项目相同,我想删除该项目 从阵列A/阵列1。好的,如果这是有效的,我想补充一些 仅当参数为时才允许删除项的更多语句 这个项目有一个特殊的价值,但我想我可以单独完成这一步

我想它适合你

你需要使你的阵列1可变

变量数组1:[项目]=

像这样过滤阵列1

let filteredArray1 = array1.filter { (item) -> Bool in
    return !array2.contains(item)
}
并使用过滤数组重新定义数组1

阵列1=过滤器阵列1

让我知道它对您有效。

更新 问题已经重申,元素将从其中一个数组中删除

您没有提供实际的代码来获取索引越界错误,但这几乎可以肯定,因为您没有考虑在使用索引时删除元素,因此您可能正在索引到一个在开始时有效但现在不再有效的区域

我的第一个建议是不要在搜索循环中进行实际的删除。有一个解决方案可以实现相同的结果,我将给出,但是除了必须非常小心索引到缩短的数组中之外,还有一个性能问题:每次删除都需要数组将后面的所有元素向下移动一个。这意味着每次删除都是一个On操作,这使得^3上的整体算法是一个On

那么你会怎么做呢?最简单的方法是创建一个只包含希望保留的元素的新数组。例如,假设您希望从array1中删除array2中的所有元素:

array1=array1.filter{!array2.contains$0} 我应该注意到,我保留以下原始答案的原因之一是,您可以使用这些方法替换array2。在某些情况下,包含$0以实现更好的性能,原始答案描述了这些情况以及如何实现

此外,即使闭包用于确定是否保留元素,因此它必须返回Bool,也没有任何东西可以阻止您在其中添加额外代码以执行您可能希望执行的任何其他工作:

array1=array1.filter { 如果array2.包含$0 { doSomethingwith:$0 return false//不保留此元素 } 返回真值 } 这同样适用于下面的所有闭合

您可以使用数组的removeAllwhere:method

array1.removeAll{array2.contains$0} 在这种情况下,如果闭包返回true,则意味着删除此元素,这与过滤器中使用的闭包的含义相反,因此,如果在其中执行其他工作,则必须考虑到这一点

我还没有查看Swift库是如何实现removeAllwhere的:但我假设它是以高效的方式而不是简单的方式完成工作的。如果您发现性能不是很好,您可以推出自己的版本

扩展数组,其中元素:equalable { 变异函数效率移动所有位置条件:元素->布尔 { 保护计数>0其他{return} 变量i=起始指数 变量iEnd=endIndex 而我 { 如果条件自我[i] { iEnd-=1 斯瓦帕蒂,伊恩 继续//注意:跳过递增i,iEnd已递减 } i+=1 } 移除ASTENDEX-iEnd } } array1.efficientRemoveAll{array2.contains$0} 而不是 实际上,移除循环中的元素是通过将它们与结束元素交换,并处理何时适当地递增来实现的。这将收集最后要删除的元素,在循环完成后可以一次性删除这些元素。因此,删除操作只需在最后进行一次,这避免了增加算法复杂性,而在循环内部删除操作则需要增加算法复杂性

由于与当前结束元素交换,此方法不会保留变化数组中元素的相对顺序

如果您想保持秩序,可以这样做:

扩展数组,其中元素:equalable { 变异函数orderPreservingRemoveAllwhere条件:元素->布尔 { 保护计数>0其他{return} 变量i=起始指数 var j=i 重复 { 斯瓦帕蒂,j if!conditionself[i]{i+=1} j+=1 }而j!=endIndex Removelastendex-i } } array1.orderPreservingRemoveAll{array2.contains$0} 如果我必须打赌的话,这将非常接近标准Swift的removeAllwhere:for数组的实现方式。它保留两个索引,一个用于保存当前最后一个元素i,另一个用于检查下一个元素j。这具有累积元素的效果,这些元素将在超过i的最后被移除

原始答案 以前的解决方案适用于小型但仍然惊人的大型阵列,但它们使用^2解决方案

如果不改变数组,可以更简洁地表达它们

array1.filter{array2.contains$0}.forEach{doSomething$0} 其中doSomething实际上不必是函数调用——只需使用$0公共元素执行任何您想执行的操作即可

通常情况下,将较小的阵列放入过滤器中会获得更好的性能

排序数组的特殊情况 如果对其中一个数组进行了排序,那么在二进制搜索中可能会获得更好的性能,而不是contains,尽管这需要元素符合Comparable。Swift标准库中没有二进制搜索,我在新的Swift算法包中也找不到,因此您需要自己实现:

扩展RandomAccessCollection,其中元素:compariable,Index==Int { func sortedContains_uu元素:元素->布尔 { 变量范围=自[…] 而range.count>0 { 设中点=range.startIndex+range.endIndex/2 如果范围[中点]==元素{返回真值} 范围=范围[中点]>元素
自己[…你的代码应该做什么?它并没有让@dan提出任何敏感的问题。你想做什么?如果我们知道你的意图,我们可以提供更好的帮助,因为当前的代码没有多大意义。我已经更新了代码,简单地解释一下你希望代码实现什么,因为我认为可能正在接近这个问题以错误的方式。也许你应该使用字典而不是数组,或者像过滤或减少数组之类的东西而不是这些嵌套循环。不管怎样,你有什么,你想完成什么,因为我觉得有一种更干净更简单的方法?好的,我已经更新了问题,请看一看谢谢你的反馈,我已经更新了question@Boothosh81我已经更新了我的答案首先谢谢你的回答,我想这几乎是我需要的,但不完全是。我已经更新了我的问题again@Boothosh81我已经更新了我的答案。@Boothrost81这种方法也应该对你有好处。为什么不只是array1=array1.filter呢{if array2.包含$0{/*附加代码*/;return false};return true}?一行看起来很难看,但这只是对SO注释的限制。它只是一个直通过滤器。
let array1: [Item] = [
    .init(name: "John"),
    .init(name: "Jack"),
    .init(name: "Soer"),
    .init(name: "Kate")
]

let array2: [Item] = [
    .init(name: "John"),
]

for item1 in array1 {
    if array2.contains(item1) {
        // Array 2 contains item from the array1 and you can perform your code.
    }
}
let filteredArray1 = array1.filter { (item) -> Bool in
    return !array2.contains(item)
}
var itemsToRemove = array1.filter { array2.contains($0) }

for item in itemsToRemove {
    if let i = array1.firstIndex(of: item) {
        // run your conditional code here.
        array1.remove(at: i)
    }
}