从Swift中删除字符串中第一个字符最简洁的方法是什么?

时间:2015-02-11 03:07:25

标签: string swift

我想从字符串中删除第一个字符。到目前为止,我提出的最简洁的事情是:

display.text = display.text!.substringFromIndex(advance(display.text!.startIndex, 1))

我知道由于Unicode,我们无法使用Int索引到字符串,但此解决方案似乎非常冗长。还有另一种我忽略的方式吗?

13 个答案:

答案 0 :(得分:183)

如果您使用 Swift 3 ,则可以忽略此答案的第二部分。好消息是,现在这又是简洁的!只需使用String的新删除(at :)方法。

var myString = "Hello, World"
myString.remove(at: myString.startIndex)

myString // "ello, World"

我喜欢全球dropFirst()功能。

let original = "Hello" // Hello
let sliced = dropFirst(original) // ello

它简短,清晰,适用于任何符合Sliceable协议的内容。

如果您使用的是Swift 2 ,则此答案已更改。您仍然可以使用dropFirst,但不能从字符串characters属性中删除第一个字符,然后将结果转换回String。 dropFirst也成为一种方法,而不是一种功能。

let original = "Hello" // Hello
let sliced = String(original.characters.dropFirst()) // ello

另一种方法是使用后缀函数来拼接字符串UTF16View。当然,之后也必须将其转换回String。

let original = "Hello" // Hello
let sliced = String(suffix(original.utf16, original.utf16.count - 1)) // ello

所有这一切都是说我最初提供的解决方案并不是最新版本的Swift中最简洁的方法。如果您正在寻找简短直观的解决方案,我建议您使用removeAtIndex()来回退@chris'解决方案。

var original = "Hello" // Hello
let removedChar = original.removeAtIndex(original.startIndex)

original // ello

正如@vacawama在下面的评论中所指出的,另一个不修改原始字符串的选项是使用substringFromIndex。

let original = "Hello" // Hello
let substring = original.substringFromIndex(advance(original.startIndex, 1)) // ello

或者,如果您正在寻找从字符串的开头和结尾删除字符,则可以使用substringWithRange。请务必在startIndex + n > endIndex - m时防范这种情况。

let original = "Hello" // Hello

let newStartIndex = advance(original.startIndex, 1)
let newEndIndex = advance(original.endIndex, -1)

let substring = original.substringWithRange(newStartIndex..<newEndIndex) // ell

也可以使用下标表示法编写最后一行。

let substring = original[newStartIndex..<newEndIndex]

答案 1 :(得分:98)

Swift 4的更新

在Swift 4中,String再次符合Collection,因此可以使用dropFirstdropLast修剪字符串的开头和结尾。结果是Substring类型,因此您需要将其传递给String构造函数以获取String

let str = "hello"
let result1 = String(str.dropFirst())    // "ello"
let result2 = String(str.dropLast())     // "hell"

dropFirst()dropLast()也会使用Int来指定要删除的字符数:

let result3 = String(str.dropLast(3))    // "he"
let result4 = String(str.dropFirst(4))   // "o"

如果指定要删除的字符数多于字符串中的字符数,则结果将为空字符串("")。

let result5 = String(str.dropFirst(10))  // ""

Swift 3的更新

如果您只想删除第一个字符并想要更改原始字符串,请参阅@ MickMacCallum的答案。如果要在流程中创建新字符串,请使用substring(from:)。如果扩展为String,则可以隐藏substring(from:)substring(to:)的丑陋,以创建有用的附加内容来修剪String的开头和结尾:

extension String {
    func chopPrefix(_ count: Int = 1) -> String {
        return substring(from: index(startIndex, offsetBy: count))
    }

    func chopSuffix(_ count: Int = 1) -> String {
        return substring(to: index(endIndex, offsetBy: -count))
    }
}

"hello".chopPrefix()    // "ello"
"hello".chopPrefix(3)   // "lo"

"hello".chopSuffix()    // "hell"
"hello".chopSuffix(3)   // "he"

如前面的dropFirstdropLast,如果字符串中没有足够的字母,这些函数将会崩溃。调用者有责任正确使用它们。这是一个有效的设计决策。可以编写它们以返回一个可选项,然后调用者必须将其解包。

Swift 2.x

唉, Swift 2 dropFirstdropLast(之前的最佳解决方案)并不像以前那样方便。如果扩展为String,则可以隐藏substringFromIndexsubstringToIndex的丑陋:

extension String {
    func chopPrefix(count: Int = 1) -> String {
         return self.substringFromIndex(advance(self.startIndex, count))
    }

    func chopSuffix(count: Int = 1) -> String {
        return self.substringToIndex(advance(self.endIndex, -count))
    }
}

"hello".chopPrefix()    // "ello"
"hello".chopPrefix(3)   // "lo"

"hello".chopSuffix()    // "hell"
"hello".chopSuffix(3)   // "he"

如前面的dropFirstdropLast,如果字符串中没有足够的字母,这些函数将会崩溃。调用者有责任正确使用它们。这是一个有效的设计决策。可以编写它们以返回一个可选项,然后调用者必须将其解包。

Swift 1.2 中,您需要像这样致电chopPrefix

"hello".chopPrefix(count: 3)  // "lo"

或者您可以在函数定义中添加下划线_以取消参数名称:

extension String {
    func chopPrefix(_ count: Int = 1) -> String {
         return self.substringFromIndex(advance(self.startIndex, count))
    }

    func chopSuffix(_ count: Int = 1) -> String {
        return self.substringToIndex(advance(self.endIndex, -count))
    }
}

答案 2 :(得分:15)

Swift 2.2

  

'advance'不可用:在索引上调用'advancedBy(n)'方法

    func chopPrefix(count: Int = 1) -> String {
        return self.substringFromIndex(self.startIndex.advancedBy(count))
    }

    func chopSuffix(count: Int = 1) -> String {
        return self.substringFromIndex(self.endIndex.advancedBy(count))
    }

Swift 3.0

    func chopPrefix(_ count: Int = 1) -> String {
        return self.substring(from: self.characters.index(self.startIndex, offsetBy: count))
    }

    func chopSuffix(_ count: Int = 1) -> String {
       return self.substring(to: self.characters.index(self.endIndex, offsetBy: -count))
    }

Swift 3.2

  

将字符串内容视为字符集合。

@available(swift, deprecated: 3.2, message: "Please use String or Substring directly")
public var characters: String.CharacterView
func chopPrefix(_ count: Int = 1) -> String {
    if count >= 0 && count <= self.count {
        return self.substring(from: String.Index(encodedOffset: count))
    }
    return ""
}

func chopSuffix(_ count: Int = 1) -> String {
    if count >= 0 && count <= self.count {
        return self.substring(to: String.Index(encodedOffset: self.count - count))
    }
    return ""
}

Swift 4

extension String {

    func chopPrefix(_ count: Int = 1) -> String {
        if count >= 0 && count <= self.count {
            let indexStartOfText = self.index(self.startIndex, offsetBy: count)
            return String(self[indexStartOfText...])
        }
        return ""
    }

    func chopSuffix(_ count: Int = 1) -> String {
        if count >= 0 && count <= self.count {
            let indexEndOfText = self.index(self.endIndex, offsetBy: -count)
            return String(self[..<indexEndOfText])
        }
        return ""
    }
}

答案 3 :(得分:12)

在Swift 2中,执行此操作:

let cleanedString = String(theString.characters.dropFirst())

我建议https://www.mikeash.com/pyblog/friday-qa-2015-11-06-why-is-swifts-string-api-so-hard.html了解Swift字符串。

答案 4 :(得分:7)

取决于你想要的最终结果(变异与非变异)。

从Swift 4.1开始:

<强>不同诱变:

var str = "hello"
str.removeFirst() // changes str 

<强> Nonmutating:

let str = "hello"
let strSlice = str.dropFirst() // makes a slice without the first letter
let str2 = String(strSlice)

备注:

  • 为了清楚起见,我在nonmutating示例中添加了一个额外的步骤。主观上,结合最后两个步骤将更简洁。
  • dropFirst的命名对我来说似乎有点奇怪,因为如果我正确理解Swift API Design GuidelinesdropFirst应该像dropingFirst那样,因为它是非突变的。只是一个想法 :)。

答案 5 :(得分:6)

这个怎么样?

s.removeAtIndex(s.startIndex)

这当然假设你的字符串是可变的。它返回已删除的字符,但会更改原始字符串。

答案 6 :(得分:5)

之前的答案非常好,但截至今天,我认为这可能是从 Swift 4 中删除字符串中第一个字符的最简洁方法:

var line: String = "This is a string..."
var char: Character? = nil

char = line.removeFirst()

print("char = \(char)")  // char = T
print("line = \(line)")  // line = his is a string ...

答案 7 :(得分:1)

我不知道开箱即用的简洁,但您可以轻松实现前缀++,例如,

public prefix func ++ <I: ForwardIndexType>(index: I) -> I {
    return advance(index, 1)
}

在此之后,您可以非常简洁地将它用于您心中的内容:

str.substringFromIndex(++str.startIndex)

答案 8 :(得分:1)

在Swift 2中使用此String扩展名:

extension String
{
    func substringFromIndex(index: Int) -> String
    {
        if (index < 0 || index > self.characters.count)
        {
            print("index \(index) out of bounds")
            return ""
        }
        return self.substringFromIndex(self.startIndex.advancedBy(index))
    }
}

display.text = display.text!.substringFromIndex(1)

答案 9 :(得分:1)

  

&#34; en_US,fr_CA,es_US&#34; .chopSuffix(5).chopPrefix(5)//&#34;,fr_CA,&#34;

extension String {
    func chopPrefix(count: Int = 1) -> String {
        return self.substringFromIndex(self.startIndex.advancedBy(count))
    }

    func chopSuffix(count: Int = 1) -> String {
        return self.substringToIndex(self.endIndex.advancedBy(-count))
    }
}

答案 10 :(得分:0)

从字符串中移除第一个字符

let choppedString = String(txtField.text!.characters.dropFirst())

答案 11 :(得分:0)

Swift3

extension String {
    func chopPrefix(_ count: UInt = 1) -> String {
        return substring(from: characters.index(startIndex, offsetBy: Int(count)))
    }

    func chopSuffix(_ count: UInt = 1) -> String {
        return substring(to: characters.index(endIndex, offsetBy: -Int(count)))
    }
}

class StringChopTests: XCTestCase {
    func testPrefix() {
        XCTAssertEqual("original".chopPrefix(0), "original")
        XCTAssertEqual("Xfile".chopPrefix(), "file")
        XCTAssertEqual("filename.jpg".chopPrefix(4), "name.jpg")
    }

    func testSuffix() {
        XCTAssertEqual("original".chopSuffix(0), "original")
        XCTAssertEqual("fileX".chopSuffix(), "file")
        XCTAssertEqual("filename.jpg".chopSuffix(4), "filename")
    }
}

答案 12 :(得分:0)

以下是chopPrefix扩展程序的 Swift4 崩溃保存版本,将chopSuffix留给社区...

extension String {
    func chopPrefix(_ count: Int = 1) -> String {
        return count>self.count ? self : String(self[index(self.startIndex, offsetBy: count)...])
    }
 }