FC2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »2021年06月
2021年06月の記事一覧

【C#】HashSet や Dictionary の AddRange  


 前回に引き続き「標準関数にあったら良いな」シリーズ(笑)。

 List には後から、要素を複数追加する AddRange() というメソッドがあるが、残念ながら、HashSetDictionary には無い。しかし、意外と複数の要素を追加したいときってあるんだよね。そんな時に便利な拡張メソッド。



●HashSet, Dictionary の AddRange
using System;
using System.Collections.Generic;

public static class Extensions //名前は任意
{
/// <summary>
/// 複数の要素を追加する(同じ値は上書きとなる)
/// ※null であっても、必ず生成される
/// 2021/06/13 Fantom
/// http://fantom1x.blog130.fc2.com/blog-entry-398.html
/// </summary>
/// <param name="set">追加先</param>
/// <param name="collection">追加ソース</param>
/// <returns></returns>
public static HashSet<T> AddRange<T>(this HashSet<T> set, IEnumerable<T> collection)
{
if (set == null)
set = new HashSet<T>();

if (collection != null)
{
foreach (var item in collection)
set.Add(item);
}
return set;
}

/// <summary>
/// 複数のキーと値ペアを追加する(同じキーは上書きとなる)
/// ※null であっても、必ず生成される.
/// 2021/06/13 Fantom
/// http://fantom1x.blog130.fc2.com/blog-entry-398.html
/// </summary>
/// <param name="dst">追加先</param>
/// <param name="src">追加ソース</param>
/// <returns></returns>
public static Dictionary<K, V> AddRange<K, V>(this Dictionary<K, V> dst, Dictionary<K, V> src)
{
if (dst == null)
dst = new Dictionary<K, V>();

if (src != null)
{
foreach (var item in src)
dst[item.Key] = item.Value;
}
return dst;
}
}

●メインコード例
using System;
using System.Collections.Generic;
using System.Linq;

var aSet = new HashSet<int>(Enumerable.Range(0, 5));
Console.WriteLine("Before : " + aSet.Dump());

var bSet = new HashSet<int>(Enumerable.Range(10, 5));
aSet.AddRange(bSet);
Console.WriteLine("After : " + aSet.Dump());

var cSet = new HashSet<int>(aSet).AddRange(bSet);
Console.WriteLine("c = a + b : " + cSet.Dump());

var aDic = new Dictionary<int, string>()
{
{ 0, "a" },
{ 1, "b" },
{ 2, "c" },
};
Console.WriteLine("Before : " + aDic.Dump());

var bDic = new Dictionary<int, string>()
{
{ 10, "x" },
{ 11, "y" },
{ 12, "z" },
};
aDic.AddRange(bDic);
Console.WriteLine("After : " + aDic.Dump());

var cDic = new Dictionary<int, string>(aDic).AddRange(bDic);
Console.WriteLine("c = a + b : " + cDic.Dump());

Before : [0, 1, 2, 3, 4]
After : [0, 1, 2, 3, 4, 10, 11, 12, 13, 14]
c = a + b : [0, 1, 2, 3, 4, 10, 11, 12, 13, 14]
Before : [[0, a], [1, b], [2, c]]
After : [[0, a], [1, b], [2, c], [10, x], [11, y], [12, z]]
c = a + b : [[0, a], [1, b], [2, c], [10, x], [11, y], [12, z]]

 要素をダンプしている Dump() は以前の記事からコピペして欲しい。

 少し標準関数の List.AddRange() と違うのは、void を返してるのではなく、コレクションを返してる所かな。こうすると、メソッドチェーンみたいにできるので、new と同時にいくつかの別コレクションを追加できたりするので、便利だ。

 とても簡単なものだけど、これもあると非常に有用なんだよね。私は結構大きなシステムを自作してるけど、大きくなるほど、こういった便利関数は欠かせなくなる(毎回似たような処理を書くのは大変な物量になるため)。実はプログラミングってこういう小さな工夫の積み重ねなんだよね(笑)。



 「これくらいのものなら、LINQ で書けばいいんじゃないの?」と思うかも知れないが、私はあまりオススメしない。というのは LINQ はそれなりにコストがかかるのと、GC を発生しやすいので、頻繁に使われるかも知れない拡張メソッド等は、割とベタな書き方をした方が速いし、GC も制御しやすいからだ。まぁ、string 系の処理はどのみち GC が発生するので使うこともあるが(しかし、できる限り StringBuilder を使う方が良い)、LINQ はどちらかというと、ランタイムで1回きりの初期化処理とか、頻繁には使わない処理用かな。特に Unity のような毎フレーム更新するような処理には気をつけて使った方が良いね。

コストのかかる操作を避ける





(関連記事)
【C#】配列 や List の TryGetValue
【C#】配列やListなどの中身(要素)を見る拡張メソッド Dump
【Unity】【C#】配列・リストのシャッフル
【C#】2次元配列(ジャグ配列・多次元配列)のソート
【C#】多次元配列とジャグ配列(2次元配列)のサイズ(長さ)、相互変換など


関連記事
スポンサーサイト



category: C#

thread: プログラミング

janre: コンピュータ

tag: C#ライブラリ  C#リファレンス  配列操作  連想配列 
tb: 0   cm: --


プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop