2次元配列のようなデータの縦横の入れ替え

# 目的
行列で言うところの転置をやります。
@IganinTea さんのエントリー
[LINQで入れ子になっているListの並びの縦横を入れ替える](http://qiita.com/IganinTea/items/2f4c8281bdb202fd627f)
中の@yuba さんの[コメント](http://qiita.com/IganinTea/items/2f4c8281bdb202fd627f#comment-5e99617e90cecea1c2e2)を参考に書けたので投稿します。

# やること
これを

||0|1|2|
|:-:|:-:|:-:|:-:|
|**0**|a|b|c|
|**1**|d|e|f|
|**2**|g|h|i|

↓みたいにする

||0|1|2|
|:-:|:-:|:-:|:-:|
|**0**|a|d|g|
|**1**|b|e|h|
|**2**|c|f|i|

# 結果
まずは結果、後で過程を示す。
こんな感じでAggregateなしでもいけました。

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values){
    return Enumerable.Range(0, values.Max(c => c.Count()))
        .Select(i => values.Select(c => i < c.Count() ? c.ElementAt(i) : default(T)));
}
```

# 元のソース
@IganinTea さんのエントリー
[LINQで入れ子になっているListの並びの縦横を入れ替える](http://qiita.com/IganinTea/items/2f4c8281bdb202fd627f)
中の@yuba さんのコメント欄のやつ

```csharp
var resultList = targetList.Aggregate(
    Enumerable.Range(0, targetList.Max(row => row.Count))
        .Select(i => new List<string>())
    ,
    (ll, row) => ll.Select((l, i) => { l.Add(row.Count <= i ? "" : row[i]); return l; })
    )
    .ToList();
    }
```

# 1段階目
とりあえず真似る.
見通しが良くなるように3項演算子を外して、中身を改行する。

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values){ 
    return values.Aggregate(
    Enumerable.Range(0, values.Max(v => v.Count())).Select(i => new List<T>()),
    (ll, row) => ll.Select((l, i) =>
    {
        l.Add(row.ElementAt(i));
        return l;
    }));
}
```

# 2段階目
columnを事前に求めてみる

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values){
 var column = values.Max(v => v.Count());
 return values.Aggregate(
     Enumerable.Range(0, column).Select(i => new List<T>()),
     (ll, row) => ll.Select((l, i) =>
     {
         l.Add(row.ElementAt(i));
         return l;
     }));
}
```

# 3段階目
Aggregateの中身がColumnのListを作っていることと理解

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values){
 var column = values.Max(v => v.Count());
 return Enumerable.Range(0, column).Select((v, i) =>
     {
         var list = new List<T>();
         foreach (var item in values)
         {
             list.Add(item.ElementAt(i));
         }
         return list;
     });
}
```

# 4段階目
foreachをselect文で書き換え

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values){
    var column = values.Max(v => v.Count());
    return Enumerable.Range(0, column).Select((v, i) =>
    {
        return values.Select(v2 => v2.ElementAt(i));
    });
}
```

# 5段階目
中のreturnを消す。
大体完成。

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values){
    var column = values.Max(v => v.Count());
    return Enumerable.Range(0, column).Select(i => values.Select(v => v.ElementAt(i)));
}
```

# 6段階目
さっきまでのはジャグ配列だと死ぬから修正。
3項演算子復活

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values){
    var column = values.Max(v => v.Count());
    return Enumerable.Range(0, column)
    .Select(i => values.Select(v => i < v.Count() ? v.ElementAt(i) : default(T)));
}
```

# 7段階目
columnの計算を戻して1つの式内で完結させる
以上の手順で書換。
Aggregateは決まるとすごいけど解読が難しい。

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values){
    return Enumerable.Range(0, values.Max(c => c.Count()))
     .Select(i => values.Select(c => i < c.Count() ? c.ElementAt(i) : default(T)));
}
```

# ちょっと改良 T[],List<T>を受けてみる
配列とリスト版を書いた。
理由はなんとなくElementAtがないやつを見たかったから。

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<T[]> values)
{
    return Enumerable.Range(0, values.Max(c => c.Length)).Select(i => values.Select(c => i < c.Length ? c[i] : default(T)));
}

public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<List<T>> values)
{
    return Enumerable.Range(0, values.Max(c => c.Count)).Select(i => values.Select(c => i < c.Count ? c[i] : default(T)));
}
```

よくよく定義を見てみたらArrayもListもIListを継承しているからまとめられた

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IList<T>> values)
{
    return Enumerable.Range(0, values.Max(c => c.Count))
    .Select(i => values.Select(c => i < c.Count ? c[i] : default(T)));
}
```

# さらに改良　空き場所にdefault(T)以外を入れてみる。
参照型を渡すと毎回参照がコピーされて1つ変更されると全部変わるからそれはできないようにする。
1つが値型に制限する。
もう1つはデリゲートで毎回作るようにして参照のコピーを作らないようにできるようにする。
var tValues = Do(values,()=>new Class());

↓みたいに参照の値を渡したら意味はないけど。
var c = new Class();
var tValues = Do(values,()=>c);


まずはIEnumerable<T>を受けるやつ。

```csharp
//参照型だと後で変更したときにほかの部分も変わるから値型のみ受け付ける。
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values, T blankValue)
    where T : struct
{
    return Enumerable.Range(0, values.Max(c => c.Count()))
    .Select(i => values.Select(c => i < c.Count() ? c.ElementAt(i) : blankValue));
}

//毎回newとかさせれば上記の問題が解消できるからFuncデリゲート入れてラムダ式とかでいけるようにする。
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IEnumerable<T>> values, Func<T> blankValue)
{
    return Enumerable.Range(0, values.Max(c => c.Count()))
    .Select(i => values.Select(c => i < c.Count() ? c.ElementAt(i) : blankValue()));
}
//使い方例
var tValues = Do(values, () => new T());
```

同じ感じでIList<T>で受けるやつ

```csharp
public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IList<T>> values, T blankValue)
    where T : struct
{
    return Enumerable.Range(0, values.Max(c => c.Count))
    .Select(i => values.Select(c => i < c.Count ? c[i] : blankValue));
}

public IEnumerable<IEnumerable<T>> Do<T>(IEnumerable<IList<T>> values, Func<T> blankValue)
{
    return Enumerable.Range(0, values.Max(c => c.Count))
    .Select(i => values.Select(c => i < c.Count ? c[i] : blankValue()));
}
```

速度的なあれは調べていません。
気が向いたら考えます。