Get a value at index from range

时间:2016-08-31 12:32:06

标签: swift range

I want to retrieve a random emoji inside the range.

let emojiRanges = [
                    0x1F601...0x1F64F,
                    0x1F680...0x1F6C0,
                ]
                let flattenEmoji = emojiRanges.flatten()
// the loop for emoji works
                for i in flattenEmoji {

                    let st = String(format:"0x%2X %@", i, String(UnicodeScalar(i)))
                    print(st)
                }

// but this is not possible to obtain value at wanted index
//there is a compiler error:
                let randomSign = String(UnicodeScalar(flattenEmoji[arc4random_uniform(UInt32(flattenEmoji.count))]))
                print("RANDOM \(randomSign)")

the error:

ViewController.swift:68:67: Cannot subscript a value of type 'FlattenBidirectionalCollection<[Range]>' (aka 'FlattenBidirectionalCollection>>') with an index of type 'UInt32'

What is the proper way to get a result?

2 个答案:

答案 0 :(得分:8)

问题在于flatten()已延迟应用,因此会返回一个特殊的FlattenBidirectionalCollection,其由FlattenBidirectionalCollectionIndex而不是Int编制索引。

因此,最简单的解决方案是简单地使用Array(_:)构造函数(或flatMap(_:))以便急切地应用范围的展平,这将创建一个数组,然后您可以使用Int

let flattenEmoji = Array(emojiRanges.flatten()) // In Swift 3, flatten() is named joined()

let randomIndex = Int(arc4random_uniform(UInt32(flattenEmoji.count)))
let randomSign = String(UnicodeScalar(flattenEmoji[randomIndex]))

如果您希望延迟展开扁平化,则可以使用集合advancedBy(_:)上的startIndex直接下标FlattenBidirectionalCollection(对于Swift 2):

let randomIndex = flattenEmoji.startIndex.advancedBy(Int(arc4random_uniform(UInt32(flattenEmoji.count))))
let randomSign = String(UnicodeScalar(flattenEmoji[randomIndex]))

在Swift 3中,作为collections move their indices,您需要使用集合的index(_:offsetBy:)方法:

let randomIndex = flattenEmoji.index(flattenEmoji.startIndex, offsetBy: Int(arc4random_uniform(UInt32(flattenEmoji.count))))

答案 1 :(得分:4)

emojiRanges声明更改为:

let emojiRanges = Array(0x1F601...0x1F64F) + Array(0x1F680...0x1F6C0)

那么生活将变得更加容易。

for i in emojiRanges {
    let st = String(format:"0x%2X %@", i, String(UnicodeScalar(i)))
    print(st)
}
randomSign中的

您应该将索引转换为Int

let randomSign = String(UnicodeScalar(emojiRanges[Int(arc4random_uniform(UInt32(emojiRanges.count)))]))
print("RANDOM \(randomSign)")