从Swift中的一系列字符初始化String

时间:2018-04-13 03:23:38

标签: swift string swift4

在我们的代码中,我们发现了一个错误,即没有正确编写字母。我们"0123456789abcdefghijklmnoqprstuvwxyz"取代let 1: String = "0"..."9" + "a"..."z" 而不是let 2: String = ("0"..."9") + ("a"..."z") 。所以我们想知道是否可以通过声明字符范围中的字符串来避免类似的拼写错误?

使用Swift 4.1+,我们尝试了:

尝试1

ClosedRange<String>
  

相邻运算符属于非关联优先级组&#39; RangeFormationPrecedence&#39;

尝试2

let 3: String = String("0"..."9") + String("a"..."z")
  

二元运算符&#39; +&#39;不能适用于两个(ClosedRange<String>)&#39;操作数

尝试3

let 4: String = (Character("0")...Character("9")) + (Character("a")...Character("z"))
  

无法为类型&#39;字符串&#39;调用初始值设定项使用类型&#39; ClosedRange<Character>&#39;

的参数列表

尝试4

let 5: String = String(Character("0")...Character("9")) + String(Character("a")...Character("z"))
  

二元运算符&#39; +&#39;不能适用于两个(ClosedRange<Character>)&#39;操作数

尝试5

$requested_Date = date("$pick_up_year/$pick_up_month/$pick_up_day");                
$sql= "SELECT users.user_id, users.user_first, users.user_phone, requests.req_id, weight FROM users INNER join requests on 
        users.user_id=requests.user_id where pick_up_date = '$requested_Date'";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
echo "<table>";
echo "<tr>
        <th>Customer ID</th>
        <th>Customer Name</th>
        <th>Customer Phone Number</th>
        <th>Request ID</th>
        <th>Weight</th>
    </tr>";
if($resultCheck > 0){
    while($row = mysqli_fetch_assoc($result)){
        echo'
    <tr>
        <th>'.$row['user_id'].'</th>
        <th>'.$row['user_first'].'</th>
        <th>'.$row['user_phone'].'</th>
        <th>'.$row['req_id'].'</th>
        <th>'.$row['weight'].'</th>';                           
    }
  

无法为类型&#39;字符串&#39;调用初始值设定项使用类型&#39; function generateToken(user) { const secret = process.env.JWT_SECRET; return jwt.sign(user, secret, { expiresIn: 10080 // in seconds }); } &#39;

的参数列表

4 个答案:

答案 0 :(得分:6)

"a"..."z"ClosedRange,但不是CountableClosedRange。 它代表s的所有字符串"a" <= s <= "z" 根据Unicode标准。这不仅仅是英文字母表中的26个小写字母,还有更多,例如“ä”,“è”,“ô”。 (比较也 ClosedInterval<String> to [String] in Swift。)

特别是"a"..."z"不是Sequence,这就是原因 String("a"..."z")不起作用。

您可以做的是创建Unicode标量值的范围 哪些是(UInt32)个数字(使用UInt32(_ v: Unicode.Scalar)初始值设定项):

let letters = UInt32("a") ... UInt32("z")
let digits = UInt32("0") ... UInt32("9")

然后创建一个包含所有Unicode标量值的字符串 (可数!)范围:

let string = String(String.UnicodeScalarView(letters.compactMap(UnicodeScalar.init)))
    + String(String.UnicodeScalarView(digits.compactMap(UnicodeScalar.init)))

print(string) // abcdefghijklmnopqrstuvwxyz0123456789

(对于4.1之前的Swift,将compactMap替换为flatMap。)

这也适用于非ASCII字符。例如:

let greekLetters = UInt32("α") ... UInt32("ω")
let greekAlphabet = String(String.UnicodeScalarView(greekLetters.compactMap(UnicodeScalar.init)))
print(greekAlphabet) // αβγδεζηθικλμνξοπρςστυφχψω

答案 1 :(得分:4)

这不一定很有说服力但是有效:

let alphas = UInt8(ascii: "a")...UInt8(ascii: "z")
let digits = UInt8(ascii: "0")...UInt8(ascii: "9")

let 6 =
      digits.reduce("") { $0 + String(Character(UnicodeScalar($1))) }
    + alphas.reduce("") { $0 + String(Character(UnicodeScalar($1))) }

print(6) // "0123456789abcdefghijklmnopqrstuvwxyz"

Ole Begemann的大力助手:https://gist.github.com/ole/d5189f20840c52eb607d5cc531e08874

答案 2 :(得分:3)

UInt32将支持Unicode范围。让我们注意一下 在以下情况下,UnicodeScalar.init?(_ v: UInt32)将返回非零值

  

v的范围是0 ... 0xD7FF或0xE000 ... 0x10FFFF

因为这是一个非常容易实现的条件,因为最多我们将有两个连接范围,我们将强制用!展开值并避免未定义的行为。

支持没有扩展名的范围

我们可以这样做:

let alphaRange = ("a" as UnicodeScalar).value...("z" as UnicodeScalar).value
let alpha = String(String.UnicodeScalarView(alphaRange.map { UnicodeScalar($0)! }))

支持扩展名为

的范围

如果我们使UnicodeScalar大幅提升,我们可以使上述更简洁。

extension UnicodeScalar : Strideable {
    public func advanced(by n: Int) -> UnicodeScalar {
        return UnicodeScalar(UInt32(n) + value)!
    }
    public func distance(to other: UnicodeScalar) -> Int {
        return Int(other.value - value)
    }
}

解决方案就变成了:

let alpha = String(String.UnicodeScalarView(("a" as UnicodeScalar)..."z"))

仅适用于ASCII范围

我们可以将自己限制为UInt8,我们不必再强制解包值,尤其是UInt8.init(ascii v: Unicode.Scalar)

let alphaRange = UInt8(ascii: "a")...UInt8(ascii: "z")
let alpha = String(String.UnicodeScalarView(alphaRange.map { UnicodeScalar($0) }))

或:

let alphaRange = UInt8(ascii: "a")...UInt8(ascii: "z")
let alpha = String(data: Data(alphaRange), encoding: .utf8)!

非常感谢Martin,Mike,jake.lange和Leo Dabus。

答案 3 :(得分:0)

将元素放在一起,我得到了以下解决方案:

extension Unicode.Scalar: Strideable {
    public func advanced(by n: Int) -> Unicode.Scalar {
        let value = self.value.advanced(by: n)
        guard let scalar = Unicode.Scalar(value) else {
            fatalError("Invalid Unicode.Scalar value:" + String(value, radix: 16))
        }
        return scalar
    }
    public func distance(to other: Unicode.Scalar) -> Int {
        return Int(other.value - value)
    }
}

extension Sequence where Element == Unicode.Scalar {
     var string: String { return String(self) }
     var characters: [Character] { return map(Character.init) }
}

extension String {
    init<S: Sequence>(_ sequence: S) where S.Element == Unicode.Scalar {
        self.init(UnicodeScalarView(sequence))
    }
}

("a"..<"z").string  // "abcdefghijklmnopqrstuvwxy"
("a"..."z").string  // "abcdefghijklmnopqrstuvwxyz"

String("a"..<"z") // "abcdefghijklmnopqrstuvwxy"
String("a"..."z") // "abcdefghijklmnopqrstuvwxyz"

("a"..<"z").characters  // ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y"] 
("a"..."z").characters // ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]