◆ .ToList()

リストでシャッフルしたり要素入れ替えたりなどするときに 元のものは維持してコピーした新しい方でシャッフルとかしたいってことはよくありますよね

なのでシャローコピー(1階層目だけコピー)する方法を探してました


JavaScript でいうなら .slice() です
function swap(arr, a, b){
    const w = arr[a]
    arr[a] = arr[b]
    arr[b] = w
    return arr
}

var arr = [1, 2, 3]
swap(arr, 0, 2)
// [3, 2, 1]
arr
// [3, 2, 1]

なにもしないと arr も返り値だけじゃなくて arr も変わってしまいますが .slice() でコピーした方を使うと
var arr = [1, 2, 3]
swap(arr.slice(), 0, 2)
// [3, 2, 1]
arr
// [1, 2, 3]

arr の方はそのままです


同じように考えると 部分配列を全範囲で作ればよさそうです

ということは .Skip(0) ?

でもこれだけだとリストになっていない 遅延評価のあとでするよ状態だから .Skip(0).ToList() になります
List<T> swap<T>(List<T> list, int a, int b) {
    var w = list[a];
    list[a] = list[b];
    list[b] = w;
    return list;
}
var list = new List<int> { 1, 2, 3 };
swap(list, 0, 2)
// List<int>(3) { 3, 2, 1 }
list
// List<int>(3) { 3, 2, 1 }

これだと list まで変わるから
var list = new List<int> { 1, 2, 3 };
swap(list.Skip(0).ToList(), 0, 2)
// List<int>(3) { 3, 2, 1 }
list
// List<int>(3) { 1, 2, 3 }

これで list は変化なし!

ここでふと思ったことが
.ToList() って新しくリストを作ってるんだから Skip なんてしなくても ToList だけでいけるんじゃないの?

やってみると
var list = new List<int> { 1, 2, 3 };
swap(list.ToList(), 0, 2)
// List<int>(3) { 3, 2, 1 }
list
// List<int>(3) { 1, 2, 3 }

ToList だけでいけました!