在条件处于Swift状态时删除集合的最后元素

在条件处于Swift状态时删除集合的最后元素,swift,Swift,我试图从字符串数组的后面删除,,,,,直到最后一项包含一些文本为止,但我的实现没有接收到, 我迄今为止的执行情况: var array = ["A", "B", "", "C", "D", " ", " ", ""] while true { if (array.last == " " || array.last == "") { array.removeLast() } else { break } } 我想要的输出是[“A”、“B”

我试图从字符串数组的后面删除
,直到最后一项包含一些文本为止,但我的实现没有接收到

我迄今为止的执行情况:

var array = ["A", "B", "", "C", "D", " ", " ", ""]

while true {
    if (array.last == " " || array.last == "") {
        array.removeLast()
    } else {
        break
    }
}
我想要的输出是
[“A”、“B”、“C”、“D”]
但是…
我当前的输出是
[“A”、“B”、“u”、“C”、“D”、“u”、“u”]
,其中
while
循环在遇到
后会简单地
中断

有什么建议吗?为什么不选择


谢谢。

将您的状态移动到
,同时
并确保您在操作后检查了正确的阵列

var数组=[“A”、“B”、“C”、“D”、“D”、“A”、“B”、“D”]
而array.last==“”| | array.last==“”{
array.removeLast()
}
打印(数组)/[“A”、“B”、“C”、“D”]

基本上,您的解决方案运行良好。但您可以使其更通用于“
”、“
”、“
”、“
”、


解决这个问题的一种方法是反向收集(这是惰性的),并丢弃不需要的项目,直到遇到想要的项目为止。然后,再次反转集合

let array = ["A", "B", "", "C", "D", " ", " ", ""]

let filtered = array.reversed().drop(while: {
    $0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
}).reversed() as [String]

print(filtered) // "["A", "B", "", "C", "D"]\n"

请注意,如果
不是正常空格,例如非中断空格(Unicode检查点U+00A0),则检查该空格可能会失败。这可能是你首先遇到的问题。因此,修剪字符串(它只从开始和结束处删除字符)并检查结果是否为空字符串。

为了好玩,让我们以一种通用的方式扩展
数组
,同时从外部提供更灵活的条件

类似于
Array
s具有
drop(while:)
,我们可以制作
dropLast(while:)
,如下所示:

extension Array {
    func dropLast(while handler: (Element)->Bool) -> Array {
        var array = self
        while let last = array.last, handler(last) {
            array.removeLast()
        }
        return array
    }
}

用法示例:
奖金: 它还可以处理其他类型的阵列,而且由于该条件没有被烘焙到功能中,因此它是灵活的和可重用的

let array = [0, 1, 2, 3, 0, 5, 6, 7, 0, -1, 0, -2]

//Drop (from tail) all numbers less than 1
let modified = array.dropLast(while: { (val) -> Bool in
    return val < 1
})
print(modified) //[0, 1, 2, 3, 0, 5, 6, 7]
let数组=[0,1,2,3,0,5,6,7,0,-1,0,-2]
//放下(从尾部)所有小于1的数字
让modified=array.dropLast(while:{(val)->Bool-in
返回值<1
})
打印(修改)/[0,1,2,3,0,5,6,7]

我不知道为什么他们有
drop(while:)
并且没有实现
dropLast(while:)
。下面的实现适用于任何集合:

extension Collection {
    func dropLast(while predicate: (Element) throws -> Bool) rethrows -> SubSequence {
        guard let index = try indices.reversed().first(where: { try !predicate(self[$0]) }) else {
            return self[startIndex..<startIndex]
        }
        return self[...index]
    }
}
扩展RangeReplaceableCollection,我们可以实现
remove(while:)
removeLast(while:)

extension RangeReplaceableCollection {
     mutating func remove(while predicate: (Element) throws -> Bool) rethrows {
        guard let index = try indices.first(where: { try !predicate(self[$0]) }) else {
            removeAll()
            return
        }
        removeSubrange(..<index)
    }
    mutating func removeLast(while predicate: (Element) throws -> Bool) rethrows {
        guard let index = try indices.reversed().first(where: { try !predicate(self[$0]) }) else {
            removeAll()
            return
        }
        removeSubrange(self.index(after: index)...)
    }
}

你可以把你的条件移动到
,而不是
true
。它实际上对我来说没有问题。我刚刚在操场上试过,结果是
[“A”,“B”,“C”,“D”]
,所以你的代码可以像你想的那样工作。在这种情况下,您不能使用do while。用户只想删除末尾的一个,而不是B和C之间的一个。嘿,我认为这个解决方案实际上比使用
while true
要好。投票。我喜欢你的答案,最好把条件放在while中,而不是while-trueAnd,
while-truen{if条件{something()}其他{break}}
while条件{something()}
@user28434:是的。但我遵循的是提问者的编码风格。顺便说一句,新方法是:
while array.last?.trimmingCharacters(in:.whitespaces and newlines).isEmpty??false{array.removeLast()}
如果决定反转数组,可能需要使用
drop(while:)
<代码>过滤器
在这里不是一个好选择。@Sulthan:噢,太好了!非常感谢您让我意识到这一点,这是一个更好的解决方案!这不应该是
returnself[startIndex。。
extension Collection {
    func dropLast(while predicate: (Element) throws -> Bool) rethrows -> SubSequence {
        guard let index = try indices.reversed().first(where: { try !predicate(self[$0]) }) else {
            return self[startIndex..<startIndex]
        }
        return self[...index]
    }
}
"123".dropLast(while: \.isWholeNumber)    // ""
"abc123".dropLast(while: \.isWholeNumber) // "abc"
"123abc".dropLast(while: \.isWholeNumber) // "123abc"
extension RangeReplaceableCollection {
     mutating func remove(while predicate: (Element) throws -> Bool) rethrows {
        guard let index = try indices.first(where: { try !predicate(self[$0]) }) else {
            removeAll()
            return
        }
        removeSubrange(..<index)
    }
    mutating func removeLast(while predicate: (Element) throws -> Bool) rethrows {
        guard let index = try indices.reversed().first(where: { try !predicate(self[$0]) }) else {
            removeAll()
            return
        }
        removeSubrange(self.index(after: index)...)
    }
}
var string = "abc123"
string.removeLast(while: \.isWholeNumber)
string  // "abc"

var string2 = "abc123"
string2.remove(while: \.isLetter)
string2 // "123"

var array = ["A", "B", "", "C", "D", " ", " ", ""]
array.removeLast { $0 == "" || $0 == " " }
array  // ["A", "B", "", "C", "D"]