Arrays 是否从对象数组中删除匹配项?
我有这样一个对象数组:Arrays 是否从对象数组中删除匹配项?,arrays,swift,Arrays,Swift,我有这样一个对象数组: var myArr = [ MyObject(name: "Abc", description: "Lorem ipsum 1."), MyObject(name: "Def", description: "Lorem ipsum 2."), MyObject(name: "Xyz", description: "Lorem ipsum 3.") ] var temp = myArr.filter { $0.name == "Def" }.first my
var myArr = [
MyObject(name: "Abc", description: "Lorem ipsum 1."),
MyObject(name: "Def", description: "Lorem ipsum 2."),
MyObject(name: "Xyz", description: "Lorem ipsum 3.")
]
var temp = myArr.filter { $0.name == "Def" }.first
myArr.removeAll { $0.name == "Def" } // Pseudo
extension Array {
mutating func removeIf(closure:(T -> Bool)) {
for (var ix = self.count - 1; ix >= 0; ix--) {
if closure(self[ix]) {
self.removeAtIndex(ix)
}
}
}
}
myArr.removeIf {$0.name == "Def"}
我知道我可以找到这样的匹配项:
var myArr = [
MyObject(name: "Abc", description: "Lorem ipsum 1."),
MyObject(name: "Def", description: "Lorem ipsum 2."),
MyObject(name: "Xyz", description: "Lorem ipsum 3.")
]
var temp = myArr.filter { $0.name == "Def" }.first
myArr.removeAll { $0.name == "Def" } // Pseudo
extension Array {
mutating func removeIf(closure:(T -> Bool)) {
for (var ix = self.count - 1; ix >= 0; ix--) {
if closure(self[ix]) {
self.removeAtIndex(ix)
}
}
}
}
myArr.removeIf {$0.name == "Def"}
但是现在如何从原始的myArr
中删除它呢?我希望过滤器。首先
可以以某种方式返回索引,这样我就可以使用removeAtIndex
。或者更好的是,我想这样做:
var myArr = [
MyObject(name: "Abc", description: "Lorem ipsum 1."),
MyObject(name: "Def", description: "Lorem ipsum 2."),
MyObject(name: "Xyz", description: "Lorem ipsum 3.")
]
var temp = myArr.filter { $0.name == "Def" }.first
myArr.removeAll { $0.name == "Def" } // Pseudo
extension Array {
mutating func removeIf(closure:(T -> Bool)) {
for (var ix = self.count - 1; ix >= 0; ix--) {
if closure(self[ix]) {
self.removeAtIndex(ix)
}
}
}
}
myArr.removeIf {$0.name == "Def"}
有什么想法吗?使用过滤器获取对象,然后在数组中循环,并使用myArr.removeAtIndex(索引)删除每个对象。使用过滤器正是这样做的。要了解正在发生的事情,请阅读下面的内容。Matts answer是一种更简洁的方法,因为您正在测试相反的匹配,因此每个对象都会被保留,除非它与您的值匹配 循环通过临时过滤器阵列
if let index = find(temp, note) {
myArr.removeAtIndex(index)
}
您没有掌握的是数组是一个结构,因此是一个值类型。它不能像类实例那样进行原地变异。因此,您将始终在幕后创建一个新数组,即使您扩展数组以编写一个变异的
removeIf
方法
因此,使用过滤器
和关闭条件的逻辑负数不会有任何缺点,也不会失去通用性:
myArr = myArr.filter { $0.name != "Def" }
例如,您可以这样编写removeIf
:
var myArr = [
MyObject(name: "Abc", description: "Lorem ipsum 1."),
MyObject(name: "Def", description: "Lorem ipsum 2."),
MyObject(name: "Xyz", description: "Lorem ipsum 3.")
]
var temp = myArr.filter { $0.name == "Def" }.first
myArr.removeAll { $0.name == "Def" } // Pseudo
extension Array {
mutating func removeIf(closure:(T -> Bool)) {
for (var ix = self.count - 1; ix >= 0; ix--) {
if closure(self[ix]) {
self.removeAtIndex(ix)
}
}
}
}
myArr.removeIf {$0.name == "Def"}
然后你可以这样使用它:
var myArr = [
MyObject(name: "Abc", description: "Lorem ipsum 1."),
MyObject(name: "Def", description: "Lorem ipsum 2."),
MyObject(name: "Xyz", description: "Lorem ipsum 3.")
]
var temp = myArr.filter { $0.name == "Def" }.first
myArr.removeAll { $0.name == "Def" } // Pseudo
extension Array {
mutating func removeIf(closure:(T -> Bool)) {
for (var ix = self.count - 1; ix >= 0; ix--) {
if closure(self[ix]) {
self.removeAtIndex(ix)
}
}
}
}
myArr.removeIf {$0.name == "Def"}
但事实上,这是对你时间的极大浪费。您在这里没有做
过滤器
没有做的事情。从myArr.removeIf
语法中可以看出,您正在适当地变异myArr
,但您没有;您正在用另一个阵列替换它。实际上,在该循环中,每次调用removatendex
都会创建另一个数组!因此,您最好使用过滤器并感到高兴。如果您想从正在迭代的数组中删除对象,您应该始终向后迭代,否则您将在某个时候处理不再有效的索引
var myArr = [
["key":"value1"],
["key":"value2"],
["key":"value3"]
]
for index in stride(from: myArr.count - 1 , to: 0, by: -1){
let x = myArr[index]
if x["key"] == "value2"{
myArr.removeAtIndex(index)
}
}
苹果在Swift 4中添加了您想要的:
var phrase = "The rain in Spain stays mainly in the plain."
let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
phrase.removeAll(where: { vowels.contains($0) })
// phrase == "Th rn n Spn stys mnly n th pln."
var phrase=“西班牙的雨水主要集中在平原。”
let元音:Set=[“a”、“e”、“i”、“o”、“u”]
短语.removeAll(其中:{votels.contains($0)})
//短语==“第n个Spn系统第n个pln。”
较老且回答深思熟虑的帖子,但作为马特上述回答的一个轶事,对于移除单个元素的简单情况,您还可以执行以下操作:
extension Array {
public func dropFirst(matching: (Element) -> Bool) -> ArraySlice<Element> {
guard let at = self.firstIndex(where: matching) else { return ArraySlice(self) }
return prefix(at) + suffix(from: at).dropFirst()
}
}
For循环是找到索引的唯一方法?。。有一个优雅的结尾吗?find
只适用于简单数组,而不适用于对象数组,对吗?无法获取find
来处理对象数组。您已经使用过滤器获取了所有对象,然后您可以使用循环中的find来从另一个数组中删除每个对象。filter
是“优雅的闭包”(顺便说一句,也是一个循环),对于如何使用每个迭代,以及他是否希望保留原始数组,可能会产生混淆?如果他只需要从数组中删除,那么简单地测试负数就会产生“从数组中删除”的效果。myArr=myArr.filter{$0.name!=“Def”}
有什么问题?因为这迫使我创建一个新变量。我想修改现有的myArr
变量。不,它没有myArr
仍然是myArr
。这是一种值类型;你不能在原地改变它!您将始终创建一个新数组,即使您编写了一个变异的removeAll
方法。这里讨论了removeAll()
实现:.Hi@matt。我如何用不同的对象替换数组中与另一个对象相同的对象,就像我们在swift中的目标C中所做的那样?我无法得到它。请帮忙。这是“正确”的答案。如果你想了解它是如何工作的,那么看看我的。了解这一点对于如何过滤至关重要,更重要的是!=作品这只是说“保留此数组中的所有对象,除非它与“Def”匹配”。我已经更新了答案,以显示实际的removeIf
实现。所以,若你们真的想,你们可以扩展数组,将其作为一种变异方法。但是,正如我也指出的那样,执行is将毫无意义。mutating func removeAtIndex()
真的创建了一个新数组吗?@MartinR当然。试试这个:vararr=[1,2,3]{didSet{println(“did”)};arr.removatendex(1)
。调用didSet
,证明数组已被替换。把变量arr
想象成一个鞋盒;我们已经从鞋盒中取出了阵列,并放入了一个不同的阵列。这就是值类型的工作方式。调用值类型实例的mutating func会将该实例替换为新实例。@matt:arr[0]=2
也会触发didSet
。这并不是说我不相信你,但如果每个数组元素的赋值都创建了一个完整的新数组,那么这个数组将无法用于任何严肃的工作(想象一个包含1000个方程和1000个未知数的线性方程解算器)。