32009


swift初心者です。csvファイルからコンマ区切りで配列に格納したものを、for文を使い２次元配列に格納したいのですが、レンジエラーが出て困っています。２次元配列の宣言の仕方がおかしいのかもしれません...迷宮入りしてます、どなたかご指摘お願いします。

[code]

    override func viewDidLoad() {
        super.viewDidLoad()
    
        func loadDat(){
            var data:[[String]] = [[]]
            do {
                let csvPath = Bundle.main.path(forResource: "data0112", ofType: "csv")
                let csvData = try String(contentsOfFile:csvPath!, encoding:String.Encoding.utf8)
                let dataList = csvData.components(separatedBy:",")
                let a:Int = 31
                var b:Int = 0
                for i in 0...a{
                   for j in 0...a{
                        data[i][j] = dataList[b]
                        b += 1
                   }
                }
            } catch {
                print(error)
            }
        }
        loadDat()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
[/code]

[![CSVファイルです](https://i.stack.imgur.com/Gtqbd.png)](https://i.stack.imgur.com/Gtqbd.png)


CC BY-SA 3.0
2017-01-20T01:47:28.580
32000
2017-01-24T02:41:55.493
19087
question
swift3
Index out of rangeエラーが出ます


### Arrayの宣言時、要素数を決めて初期化する

まず、`Array`は、このような代入はできません。

[code]

    var array = [1, 2, 3]
    array[3] = 4
    // fatal error: Index out of range
    
[/code]

要素が3つしかないのに、4番目に代入しようとした、というエラーが出ます。

最初から、`Array`の要素数を決められる場合は、その要素数で、`Array`を初期化します。

[code]

    var array = [Int](repeating: 0, count: 4)
    // [0, 0, 0, 0]
    
    var data = [[String]](repeating: [String](repeating: "", count: 32), count: 32)
    
[/code]

32×32の二次元配列`data`を初期化するには、上のように、初期化も多重にします。  
`Array`の要素数が当初不定の場合、`append`メソッドを使って、`Array`に要素を追加していきます。

[code]

    var array: [Int] = []
    array.append(100)
    array.append(200)
    // [100, 200]
    
[/code]

* * *

### 単純ミスで、プログラムをクラッシュさせない

配列`data`の初期化が解決したら、つぎに繰り返し文を見直します。現状では、配列`dataList`の要素数が、32×32よりひとつでも不足すると、やはり「Out
of range」でクラッシュしてしまいます。繰り返しの回数を、`dataList.count`で終わらせることを考えます。

[code]

    let number = 32
    var data = [[String]](repeating: [String](repeating: "", count: number), count: number)
    
    if let csvUrl = Bundle.main.url(forResource: "data0112", withExtension: "csv") {
        do {
            let csvData = try String(contentsOf: csvUrl)
            let dataList = csvData.components(separatedBy: ",")
            if dataList.count > number * number {
                // 要素数が、32×32を超える場合、なにかする。
                return
            }
            for (n, item) in dataList.enumerated() {
                data[n / number][n % number] = item
            }
        } catch {
            fatalError("Not found CSV files")
        }
    }
    
[/code]

`Array`のメソッド`enumerated()`について：これは、インデックスと配列の要素からなるTupleの配列を返します。`for i in
0..<dataList.count`と書くより、すこしスマートな記述ができます。


CC BY-SA 3.0
2017-01-20T04:36:57.257
32009
2017-01-20T05:22:37.753
2017-01-20T05:22:37.753
18540
18540
32000
answer