Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a value at index from range

Tags:

range

swift

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?

like image 825
Vyacheslav Avatar asked Aug 31 '16 12:08

Vyacheslav


People also ask

Can INDEX function return an array?

If array has more than one row and more than one column, and only row_num or column_num is used, INDEX returns an array of the entire row or column in array.

Can you index a range in Python?

What is Python Range? Python range() is a built-in function available with Python from Python(3. x), and it gives a sequence of numbers based on the start and stop index given. In case the start index is not given, the index is considered as 0, and it will increment the value by 1 till the stop index.

How do you find the index of an array variable?

To find the position of an element in an array, you use the indexOf() method. This method returns the index of the first occurrence the element that you want to find, or -1 if the element is not found.


2 Answers

The problem is that flatten() is lazily applied, and therefore returns a special FlattenBidirectionalCollection, which is indexed by a FlattenBidirectionalCollectionIndex, rather than an Int.

The simplest solution therefore would be to simply use the Array(_:) constructor (or flatMap(_:)) in order to eagerly apply the flattening of the ranges, which will create an array that you can then subscript with an 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]))

If you wish to keep the flattening being lazily applied, you could subscript the FlattenBidirectionalCollection directly (for Swift 2) through using advancedBy(_:) on the collection's startIndex:

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

In Swift 3, as collections move their indices, you'd want use the collection's index(_:offsetBy:) method instead:

let randomIndex = flattenEmoji.index(flattenEmoji.startIndex, offsetBy: Int(arc4random_uniform(UInt32(flattenEmoji.count))))
like image 73
Hamish Avatar answered Sep 27 '22 12:09

Hamish


Change emojiRanges declaration to this:

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

then life will become much easier.

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

in randomSign you should convert index to Int

let randomSign = String(UnicodeScalar(emojiRanges[Int(arc4random_uniform(UInt32(emojiRanges.count)))]))
print("RANDOM \(randomSign)")
like image 37
Shadow Of Avatar answered Sep 25 '22 12:09

Shadow Of